cluster_linearize: add tests and benchmarks for chain and tree-shaped clusters #34625

pull HowHsu wants to merge 3 commits into bitcoin:master from HowHsu:linearize-tests changing 2 files +261 −0
  1. HowHsu commented at 2:55 PM on February 19, 2026: contributor
                                                                                 

    Summary

                                                                                 

    This PR adds correctness tests and benchmarks specifically targeting chain and tree-shaped cluster topologies, which are both common in real-world mempools and structurally special with respect to PostLinearize.
    Commits:

    • a11760f9 cluster_linearize: add chain cluster benchmarks for PostLinearize and Linearize
    • 4b7e2b28 cluster_linearize: test PostLinearize optimality on random tree-shaped clusters
    • 0725aa05 cluster_linearize: test PostLinearize optimality on random chain clusters

                                                                                 

    Motivation

                                                                                 

    PostLinearize gives an optimality guarantee for clusters with a tree shape: if every transaction has at most one direct parent, or every transaction has at most one direct child, the result is provably optimal. A chain (tx_0 → tx_1 → ... → tx_{N-1}) satisfies both conditions simultaneously.
    These structural guarantees lacked dedicated test coverage and chain-specific benchmarks, making it hard to observe the effect of topology-aware optimizations on linearization performance.

                                                                                 

    Changes

                                                                                 

    Tests (src/test/cluster_linearize_tests.cpp)

                                                                                 

    postlinearize_tree_optimal_tests

                                                                                 

    Adds MakeRandomTreeGraph(), which generates random tree-shaped dependency graphs in two orientations:

    • Upright tree: transaction i picks a random parent from [0, i), so every node has at most one direct parent.
    • Reverse tree: transaction i picks a random child from [0, i), so every node has at most one direct child.

    For random trees of sizes 5..30, the test verifies:

    1. PostLinearize produces a linearization of equal quality to the exhaustive Linearize() result (as guaranteed by PostLinearize's interface for tree-shaped inputs).
    2. Idempotency: a second PostLinearize pass produces no change.

    postlinearize_chain_optimal_tests

                                                                                 

    Adds MakeRandomChainGraph(), which generates random linear chain dependency graphs (tx_0 → tx_1 → ... → tx_{N-1}) with randomized feerates.
    For chains of sizes 5..50, the test verifies:

    1. PostLinearize produces a linearization of equal quality to the exhaustive Linearize() result. A chain satisfies both tree-shape conditions simultaneously, so optimality is guaranteed.
    2. Idempotency: a second PostLinearize pass produces no change.

    Benchmarks (src/bench/cluster_linearize.cpp)

                                                                                 

    Adds MakeChainGraph() to build deterministic random chain dependency graphs
    (tx_0 → tx_1 → ... → tx_{N-1}) with randomized feerates seeded deterministically from the cluster size, and two sets of chain-specific benchmarks:

    • PostLinearizeChain{16,32,48,64,75,99}Tx: measure PostLinearize throughput on chain-shaped clusters across a range of sizes.
    • LinearizeOptimallyChainTotal_{9,16,32,48,63}tx: measure the total time for Linearize to reach an optimal result on chain-shaped clusters.

    Chain clusters are a common real-world mempool pattern (each transaction spending an output of the previous one). Dedicated benchmarks make it easy to observe the effect of topology-specific linearization optimizations as they are developed.

  2. DrahtBot commented at 2:55 PM on February 19, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35414 (iwyu: Fix warnings in src/bench and treat them as error by hebasto)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  3. HowHsu force-pushed on Feb 19, 2026
  4. DrahtBot added the label CI failed on Feb 19, 2026
  5. fanquake commented at 3:29 PM on February 19, 2026: member

    https://github.com/bitcoin/bitcoin/actions/runs/22186932377/job/64163346820?pr=34625#step:11:2598:

    [97](https://github.com/bitcoin/bitcoin/actions/runs/22186932377/job/64163346820?pr=34625#step:11:2598)
    stderr:
    /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79: runtime error: shift exponent 32 is too large for 32-bit type 'DepGraphIndex' (aka 'unsigned int')
        [#0](/bitcoin-bitcoin/0/) 0x5803c8353259 in (anonymous namespace)::BenchLinearizeOptimallyChainTotal(ankerl::nanobench::Bench&, std::vector<unsigned int, std::allocator<unsigned int>> const&) /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79
        [#1](/bitcoin-bitcoin/1/) 0x5803c8353259 in LinearizeOptimallyChainTotal(ankerl::nanobench::Bench&) /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:216:5
        [#2](/bitcoin-bitcoin/2/) 0x5803c8280446 in std::function<void (ankerl::nanobench::Bench&)>::operator()(ankerl::nanobench::Bench&) const /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_function.h:591:9
        [#3](/bitcoin-bitcoin/3/) 0x5803c8280446 in benchmark::BenchRunner::RunAll(benchmark::Args const&) /home/admin/actions-runner/_work/_temp/src/bench/bench.cpp:121:13
        [#4](/bitcoin-bitcoin/4/) 0x5803c8271b85 in main /home/admin/actions-runner/_work/_temp/src/bench/bench_bitcoin.cpp:135:9
        [#5](/bitcoin-bitcoin/5/) 0x74f0319481c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
        [#6](/bitcoin-bitcoin/6/) 0x74f03194828a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
        [#7](/bitcoin-bitcoin/7/) 0x5803c8184974 in _start (/home/admin/actions-runner/_work/_temp/build/bin/bench_bitcoin+0x142e974) (BuildId: 18390638316178c3c31ae8dc10b5258eb5361226)
    
    SUMMARY: UndefinedBehaviorSanitizer: invalid-shift-exponent /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79
    
  6. HowHsu commented at 4:02 PM on February 19, 2026: contributor

    https://github.com/bitcoin/bitcoin/actions/runs/22186932377/job/64163346820?pr=34625#step:11:2598:

    
    [97](https://github.com/bitcoin/bitcoin/actions/runs/22186932377/job/64163346820?pr=34625#step:11:2598)
    
    stderr:
    
    /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79: runtime error: shift exponent 32 is too large for 32-bit type 'DepGraphIndex' (aka 'unsigned int')
    
        [#0](/bitcoin-bitcoin/0/) 0x5803c8353259 in (anonymous namespace)::BenchLinearizeOptimallyChainTotal(ankerl::nanobench::Bench&, std::vector<unsigned int, std::allocator<unsigned int>> const&) /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79
    
        [#1](/bitcoin-bitcoin/1/) 0x5803c8353259 in LinearizeOptimallyChainTotal(ankerl::nanobench::Bench&) /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:216:5
    
        [#2](/bitcoin-bitcoin/2/) 0x5803c8280446 in std::function<void (ankerl::nanobench::Bench&)>::operator()(ankerl::nanobench::Bench&) const /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_function.h:591:9
    
        [#3](/bitcoin-bitcoin/3/) 0x5803c8280446 in benchmark::BenchRunner::RunAll(benchmark::Args const&) /home/admin/actions-runner/_work/_temp/src/bench/bench.cpp:121:13
    
        [#4](/bitcoin-bitcoin/4/) 0x5803c8271b85 in main /home/admin/actions-runner/_work/_temp/src/bench/bench_bitcoin.cpp:135:9
    
        [#5](/bitcoin-bitcoin/5/) 0x74f0319481c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
    
        [#6](/bitcoin-bitcoin/6/) 0x74f03194828a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
    
        [#7](/bitcoin-bitcoin/7/) 0x5803c8184974 in _start (/home/admin/actions-runner/_work/_temp/build/bin/bench_bitcoin+0x142e974) (BuildId: 18390638316178c3c31ae8dc10b5258eb5361226)
    
    
    
    SUMMARY: UndefinedBehaviorSanitizer: invalid-shift-exponent /home/admin/actions-runner/_work/_temp/src/bench/cluster_linearize.cpp:130:79
    
    

    Thanks, I'll look into it tomorrow.

  7. HowHsu force-pushed on Feb 20, 2026
  8. cluster_linearize: add chain cluster benchmarks for PostLinearize and Linearize
    Add MakeChainGraph() to build deterministic random chain dependency graphs
    (tx0->tx1->...->tx_{n-1}) with randomized feerates, and two sets of
    chain-specific benchmarks:
    
    - PostLinearizeChain{16,32,48,64,75,99}Tx: measure PostLinearize throughput
      on chain-shaped clusters across a range of sizes.
    - LinearizeOptimallyChainTotal_{9,16,32,48,63}tx: measure the total time for
      Linearize to reach an optimal result on chain-shaped clusters.
    
    Chain clusters are a common real-world mempool pattern (each transaction
    spending an output of the previous one). Dedicated benchmarks make it easy
    to observe the effect of topology-specific linearization optimizations.
    386f6084cc
  9. cluster_linearize: test PostLinearize optimality on random tree-shaped clusters
    Add MakeRandomTreeGraph() which generates random tree-shaped dependency graphs
    in two orientations:
    - Upright tree: each transaction i picks a random parent from [0, i), giving
      a DAG where every node has at most one direct parent.
    - Reverse tree: each transaction i picks a random child from [0, i), giving
      a DAG where every node has at most one direct child.
    
    Add postlinearize_tree_optimal_tests which verifies, for random trees of
    various sizes (5..30 transactions), that PostLinearize matches the quality of
    the exhaustive Linearize() result, as guaranteed by PostLinearize's interface.
    Also verifies idempotency: a second PostLinearize pass produces no change.
    e25f63ba6e
  10. cluster_linearize: test PostLinearize optimality on random chain clusters
    Add MakeRandomChainGraph() which generates random linear chain dependency
    graphs (tx0->tx1->...->tx_{n-1}) with randomized feerates.
    
    Add postlinearize_chain_optimal_tests which verifies, for chains of various
    sizes (5..50 transactions), that PostLinearize matches the quality of the
    exhaustive Linearize() result. A chain satisfies both tree-shape conditions
    simultaneously (each transaction has at most one parent and at most one
    child), so PostLinearize is guaranteed to produce an optimal linearization.
    Also verifies idempotency: a second PostLinearize pass produces no change.
    0a3aacde22
  11. HowHsu force-pushed on Feb 20, 2026
  12. DrahtBot removed the label CI failed on Feb 20, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-06-01 18:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me