test: Remove polling loop from test_runner (take 2) #33141

pull maflcko wants to merge 1 commits into bitcoin:master from maflcko:2508-ci changing 1 files +45 −32
  1. maflcko commented at 7:56 am on August 6, 2025: member

    (This picks up my prior attempt from #13384)

    Currently, the test_runner is using a time.sleep before polling to check if any tests have completed. This is largely fine when running a few tests, or when the tests take a long time.

    However, when running many fast tests, this can accumulate and leave the CPU idle for no reason.

    A trivial improvement would be to only sleep when really needed:

     0diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
     1index 7c8c15f391..1d9f28cee4 100755
     2--- a/test/functional/test_runner.py
     3+++ b/test/functional/test_runner.py
     4@@ -747,7 +747,6 @@ class TestHandler:
     5         dot_count = 0
     6         while True:
     7             # Return all procs that have finished, if any. Otherwise sleep until there is one.
     8-            time.sleep(.5)
     9             ret = []
    10             for job in self.jobs:
    11                 (name, start_time, proc, testdir, log_out, log_err) = job
    12@@ -771,6 +770,7 @@ class TestHandler:
    13                     ret.append((TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr, skip_reason))
    14             if ret:
    15                 return ret
    16+            time.sleep(.5)
    17             if self.use_term_control:
    18                 print('.', end='', flush=True)
    19             dot_count += 1
    

    However, ideally there is no sleep at all. So do that by using a ThreadPoolExecutor.

    This can be tested via something like:

    0time ./bld-cmake/test/functional/test_runner.py $(for i in {1..200}; do echo -n "tool_rpcauth "; done) -j 200
    

    The result should show:

    • Current master is the slowest
    • The “sleep patch” from above is a bit faster (1.5x improvement)
    • This pull request is the fastest (2x improvement)
  2. DrahtBot added the label Tests on Aug 6, 2025
  3. DrahtBot commented at 7:56 am on August 6, 2025: contributor

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

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33141.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK l0rinc
    Stale ACK Eunovo

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  4. l0rinc commented at 3:59 am on August 7, 2025: contributor

    I ran the 3 versions you mentioned with hyperfine, 10 runs each:

     0COMMITS="d767503b6a2618e0c99407acf98f3bd19fb7defd 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7 35e91b899dac689b24a8a95fcef083affc695d1e"; \
     1PARALLEL=200; RUNS=10; \
     2CC=gcc; CXX=g++; \
     3BUILD='Release'; \
     4TEST_LIST=$(python3 -c "print('tool_rpcauth ' * $PARALLEL)"); \
     5(echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
     6hyperfine \
     7  --sort command \
     8  --runs $RUNS \
     9  --parameter-list COMMIT ${COMMITS// /,} \
    10  --prepare "git checkout {COMMIT}; git clean -fxd; git reset --hard && cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${BUILD} && ninja -C build" \
    11  "build/test/functional/test_runner.py $TEST_LIST -j$PARALLEL"
    

    d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation 5bb380ec87 test: sleep patch 35e91b899d test: Remove polling loop from test_runner

     0Benchmark 1: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth too
     1l_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_r
     2pcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpca
     3uth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     4  Time (mean ± σ):      7.233 s ±  0.057 s    [User: 41.885 s, System: 4.270 s]
     5  Range (min … max):    7.085 s …  7.286 s    10 runs
     6
     7Benchmark 2: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth too
     8l_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_r
     9pcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpca
    10uth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    11  Time (mean ± σ):      3.827 s ±  0.127 s    [User: 41.717 s, System: 4.300 s]
    12  Range (min … max):    3.726 s …  4.174 s    10 runs
    13
    14Benchmark 3: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth too
    15l_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_r
    16pcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpca
    17uth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    18  Time (mean ± σ):      3.696 s ±  0.026 s    [User: 41.489 s, System: 4.324 s]
    19  Range (min … max):    3.681 s …  3.768 s    10 runs
    

    And I’m getting slightly different results than you:

    0Relative speed comparison
    1    1.96 ±  0.02  ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    2    1.04 ±  0.04  ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    3    1.00          ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    

    Tried a few different combinations:

     0COMMITS="d767503b6a2618e0c99407acf98f3bd19fb7defd 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7 35e91b899dac689b24a8a95fcef083affc695d1e"; \
     1PARALLEL=200; RUNS=3; \
     2CC=gcc; CXX=g++; \
     3BUILD='Debug'; \
     4TEST_LIST=$(python3 -c "print('tool_rpcauth ' * $PARALLEL)"); \
     5(echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
     6hyperfine \
     7  --sort command \
     8  --runs $RUNS \
     9  --parameter-list COMMIT ${COMMITS// /,} \
    10  --prepare "git checkout {COMMIT}; git clean -fxd; git reset --hard && cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${BUILD} && ninja -C build" \
    11  "./build/test/functional/test_runner.py $TEST_LIST -j$PARALLEL"
    12
    13d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation
    145bb380ec87 test: sleep patch
    1535e91b899d test: Remove polling loop from test_runner
    16
    17Benchmark 1: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    18  Time (mean ± σ):      7.716 s ±  0.013 s    [User: 42.081 s, System: 4.335 s]
    19  Range (min  max):    7.704 s   7.731 s    3 runs
    20
    21Benchmark 2: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    22  Time (mean ± σ):      4.301 s ±  0.034 s    [User: 42.486 s, System: 4.310 s]
    23  Range (min  max):    4.263 s   4.328 s    3 runs
    24
    25Benchmark 3: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    26  Time (mean ± σ):      4.169 s ±  0.028 s    [User: 41.859 s, System: 4.345 s]
    27  Range (min  max):    4.140 s   4.195 s    3 runs
    28
    29Relative speed comparison
    30        1.85 ±  0.01  ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth  -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    31        1.03 ±  0.01  ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth  -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    32        1.00          ./build/test/functional/test_runner.py tool_rpcauth [...] tool_rpcauth  -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    
     0COMMITS="d767503b6a2618e0c99407acf98f3bd19fb7defd 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7 35e91b899dac689b24a8a95fcef083affc695d1e"; \
     1PARALLEL=200; RUNS=10; \
     2CC=clang; CXX=clang++;
     3BUILD='Release'; \
     4TEST_LIST=$(python3 -c "print('tool_rpcauth ' * $PARALLEL)"); \
     5(echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
     6hyperfine \
     7  --sort command \
     8  --runs $RUNS \
     9  --parameter-list COMMIT ${COMMITS// /,} \
    10  --prepare "git checkout {COMMIT}; git clean -fxd; git reset --hard && cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${BUILD} && ninja -C build" \
    11  "build/test/functional/test_runner.py $TEST_LIST -j$PARALLEL"
    12
    13d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation
    145bb380ec87 test: sleep patch
    1535e91b899d test: Remove polling loop from test_runner
    16
    17Benchmark 1: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    18  Time (mean ± σ):      9.829 s ±  0.183 s    [User: 38.943 s, System: 4.407 s]
    19  Range (min  max):    9.694 s  10.320 s    10 runs
    20
    21Benchmark 2: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    22  Time (mean ± σ):      7.063 s ±  0.193 s    [User: 38.883 s, System: 4.408 s]
    23  Range (min  max):    6.796 s   7.267 s    10 runs
    24
    25Benchmark 3: ./build/test/functional/test_runner.py tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth tool_rpcauth  -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    26  Time (mean ± σ):      6.904 s ±  0.213 s    [User: 38.949 s, System: 4.386 s]
    27  Range (min  max):    6.649 s   7.267 s    10 runs
    28
    29Relative speed comparison
    30        1.42 ±  0.05  ./build/test/functional/test_runner.py [...] tool_rpcauth  -j200 (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    31        1.02 ±  0.04  ./build/test/functional/test_runner.py [...] tool_rpcauth tool_rpcauth  -j200 (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    32        1.00          ./build/test/functional/test_runner.py [...] tool_rpcauth tool_rpcauth  -j200 (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    

    So this is obviously faster for many tiny tests, will run the same for the full test suite and do a full code review later. Concept ACK

  5. maflcko commented at 6:29 am on August 7, 2025: member

    So this is obviously faster for many tiny tests, will run the same for the full test suite and do a full code review later.

    Nice. Thanks for testing and confirming that the code without any sleep is the fastest of the 3 versions. I think benchmarking the full test suite may be difficult, because it has internal noise higher than the savings here. At least back in #13384 (comment), it was hard to measure, but maybe there is less noise now and this can be measured now.

  6. l0rinc commented at 4:56 pm on August 7, 2025: contributor

    it has internal noise higher than the savings here

    Sure, but I’m just running them a lot of times, the trends are obvious this way.

    will run the same for the full test suite

    I have measured running the tests with the 3 setups with 1-6x the nproc for parallelism. The 3 solutions all scale well beyond the number of cpus (I’m now running the same until 8x on a different platform to confirm the findings).

      0COMMITS="d767503b6a2618e0c99407acf98f3bd19fb7defd 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7 35e91b899dac689b24a8a95fcef083affc695d1e"; \
      1RUNS=3; \
      2CC=gcc; CXX=g++; \
      3BUILD='Release'; \
      4(echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
      5hyperfine \
      6  --sort command \
      7  --runs $RUNS \
      8  --parameter-list COMMIT ${COMMITS// /,} \
      9  --parameter-list FACTOR $(seq -s, 1 6) \
     10  --prepare "git checkout {COMMIT}; git clean -fxd; git reset --hard &&  cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${BUILD} && ninja -C build " \
     11  "build/test/functional/test_runner.py -j\$(({FACTOR} * $(nproc))) || true"
     12
     13d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation
     145bb380ec87 test: sleep patch
     1535e91b899d test: Remove polling loop from test_runner
     16
     17Benchmark 1: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     18  Time (mean ± σ):     161.044 s ± 14.549 s    [User: 727.494 s, System: 95.580 s]
     19  Range (min … max):   151.727 s … 177.809 s    3 runs
     20 
     21Benchmark 2: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     22  Time (mean ± σ):     162.738 s ±  4.422 s    [User: 745.107 s, System: 95.168 s]
     23  Range (min … max):   157.762 s … 166.217 s    3 runs
     24 
     25Benchmark 3: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     26  Time (mean ± σ):     164.559 s ±  2.955 s    [User: 740.193 s, System: 96.168 s]
     27  Range (min … max):   161.401 s … 167.256 s    3 runs
     28 
     29Benchmark 4: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     30  Time (mean ± σ):     123.475 s ±  0.815 s    [User: 881.995 s, System: 112.519 s]
     31  Range (min … max):   122.815 s … 124.385 s    3 runs
     32 
     33Benchmark 5: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     34  Time (mean ± σ):     123.129 s ±  2.608 s    [User: 881.362 s, System: 112.607 s]
     35  Range (min … max):   121.520 s … 126.137 s    3 runs
     36 
     37  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
     38 
     39Benchmark 6: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     40  Time (mean ± σ):     122.078 s ±  0.827 s    [User: 857.404 s, System: 113.242 s]
     41  Range (min … max):   121.211 s … 122.858 s    3 runs
     42 
     43Benchmark 7: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     44  Time (mean ± σ):     111.159 s ±  1.883 s    [User: 900.148 s, System: 123.057 s]
     45  Range (min … max):   109.349 s … 113.108 s    3 runs
     46 
     47Benchmark 8: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     48  Time (mean ± σ):     110.060 s ±  0.637 s    [User: 909.104 s, System: 123.203 s]
     49  Range (min … max):   109.374 s … 110.634 s    3 runs
     50 
     51Benchmark 9: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     52  Time (mean ± σ):     107.698 s ±  0.202 s    [User: 908.138 s, System: 123.326 s]
     53  Range (min … max):   107.530 s … 107.922 s    3 runs
     54 
     55Benchmark 10: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     56  Time (mean ± σ):     99.439 s ±  0.353 s    [User: 876.245 s, System: 123.568 s]
     57  Range (min … max):   99.055 s … 99.750 s    3 runs
     58 
     59Benchmark 11: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     60  Time (mean ± σ):     100.665 s ±  0.930 s    [User: 878.436 s, System: 123.433 s]
     61  Range (min … max):   99.654 s … 101.483 s    3 runs
     62 
     63Benchmark 12: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     64  Time (mean ± σ):     98.818 s ±  0.490 s    [User: 891.573 s, System: 122.992 s]
     65  Range (min … max):   98.278 s … 99.234 s    3 runs
     66 
     67Benchmark 13: build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     68  Time (mean ± σ):     96.018 s ±  1.705 s    [User: 847.227 s, System: 123.800 s]
     69  Range (min … max):   95.008 s … 97.986 s    3 runs
     70 
     71  Warning: The first benchmarking run for this command was significantly slower than the rest (97.986 s). This could be caused by (filesystem) caches that were not filled until after the first run. You are already using the '--prepare' option which can be used to clear caches. If you did not use a cache-clearing command with '--prepare', you can either try that or consider using the '--warmup' option to fill those caches before the actual benchmark.
     72 
     73Benchmark 14: build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     74  Time (mean ± σ):     97.786 s ±  1.161 s    [User: 854.971 s, System: 123.509 s]
     75  Range (min … max):   96.573 s … 98.888 s    3 runs
     76 
     77Benchmark 15: build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     78  Time (mean ± σ):     97.968 s ±  1.246 s    [User: 876.036 s, System: 123.396 s]
     79  Range (min … max):   96.862 s … 99.317 s    3 runs
     80 
     81Benchmark 16: build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     82  Time (mean ± σ):     97.557 s ±  0.795 s    [User: 864.526 s, System: 124.178 s]
     83  Range (min … max):   96.685 s … 98.242 s    3 runs
     84 
     85Benchmark 17: build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     86  Time (mean ± σ):     98.179 s ±  1.145 s    [User: 863.995 s, System: 124.434 s]
     87  Range (min … max):   97.295 s … 99.473 s    3 runs
     88 
     89Benchmark 18: build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     90  Time (mean ± σ):     96.079 s ±  0.906 s    [User: 857.862 s, System: 124.003 s]
     91  Range (min … max):   95.159 s … 96.970 s    3 runs
     92 
     93Relative speed comparison
     94        1.68 ±  0.15  build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     95        1.69 ±  0.06  build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     96        1.71 ±  0.04  build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
     97        1.29 ±  0.02  build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     98        1.28 ±  0.04  build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     99        1.27 ±  0.02  build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    100        1.16 ±  0.03  build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    101        1.15 ±  0.02  build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    102        1.12 ±  0.02  build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    103        1.04 ±  0.02  build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    104        1.05 ±  0.02  build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    105        1.03 ±  0.02  build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    106        1.00          build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    107        1.02 ±  0.02  build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    108        1.02 ±  0.02  build/test/functional/test_runner.py -j$((5 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    109        1.02 ±  0.02  build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    110        1.02 ±  0.02  build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    111        1.00 ±  0.02  build/test/functional/test_runner.py -j$((6 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    

    Which indicates to me that the new solution scales a bit better - but since we haven’t even hit the bottom yet (surprisingly), I’ll post those in a follow-up.

  7. maflcko commented at 5:09 pm on August 7, 2025: member

    Which indicates to me that the new solution scales a bit better - but since we haven’t even hit the bottom yet (surprisingly), I’ll post those in a follow-up.

    Thanks for the benchmarks, but honestly, I can’t see that the new solution scales better. You only did 3 runs for each point, and the error bars overlap with the other points each time. Also the hyperfine output has warnings about outliers. I guess you’d have to run at least 100 times for each data point (not saying you should :sweat_smile:, I am happy with the previous benchmarks already).

    Also, I am thinking you are already saturated at 100 seconds, because the slowest test likely takes this amount of time. No amount of parallelism can make it faster.

  8. l0rinc commented at 6:13 am on August 13, 2025: contributor

    Redid only 1-4x, with 20 runs for stability to see if these speedups apply to our test suite as well.

    Running it on a more powerful i9 with SSD:

     0d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation
     15bb380ec87 test: sleep patch
     235e91b899d test: Remove polling loop from test_runner
     3
     4Benchmark 1: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
     5  Time (mean ± σ):     162.617 s ±  4.057 s    [User: 742.563 s, System: 95.831 s]
     6  Range (min … max):   153.539 s … 169.594 s    20 runs
     7 
     8Benchmark 2: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
     9  Time (mean ± σ):     166.120 s ±  1.751 s    [User: 746.994 s, System: 95.786 s]
    10  Range (min … max):   162.345 s … 170.193 s    20 runs
    11 
    12Benchmark 3: build/test/functional/test_runner.py -j$((1 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    13  Time (mean ± σ):     165.285 s ±  1.679 s    [User: 743.584 s, System: 96.084 s]
    14  Range (min … max):   162.273 s … 168.493 s    20 runs
    15 
    16Benchmark 4: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    17  Time (mean ± σ):     123.485 s ±  1.311 s    [User: 861.322 s, System: 112.273 s]
    18  Range (min … max):   121.381 s … 125.718 s    20 runs
    19 
    20Benchmark 5: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    21  Time (mean ± σ):     123.578 s ±  1.149 s    [User: 865.509 s, System: 112.239 s]
    22  Range (min … max):   121.861 s … 126.296 s    20 runs
    23 
    24Benchmark 6: build/test/functional/test_runner.py -j$((2 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    25  Time (mean ± σ):     122.229 s ±  1.581 s    [User: 867.603 s, System: 112.883 s]
    26  Range (min … max):   119.546 s … 124.407 s    20 runs
    27 
    28Benchmark 7: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    29  Time (mean ± σ):     110.005 s ±  1.110 s    [User: 904.411 s, System: 122.869 s]
    30  Range (min … max):   108.654 s … 111.472 s    20 runs
    31 
    32Benchmark 8: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    33  Time (mean ± σ):     111.199 s ±  1.291 s    [User: 902.330 s, System: 122.718 s]
    34  Range (min … max):   108.685 s … 114.161 s    20 runs
    35 
    36Benchmark 9: build/test/functional/test_runner.py -j$((3 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    37  Time (mean ± σ):     109.771 s ±  1.615 s    [User: 897.538 s, System: 122.906 s]
    38  Range (min … max):   107.295 s … 113.223 s    20 runs
    39 
    40Benchmark 10: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    41  Time (mean ± σ):     100.538 s ±  1.568 s    [User: 890.148 s, System: 123.298 s]
    42  Range (min … max):   97.325 s … 103.165 s    20 runs
    43 
    44Benchmark 11: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    45  Time (mean ± σ):     100.561 s ±  1.307 s    [User: 881.061 s, System: 123.444 s]
    46  Range (min … max):   98.469 s … 103.547 s    20 runs
    47 
    48Benchmark 12: build/test/functional/test_runner.py -j$((4 * 16)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    49  Time (mean ± σ):     100.220 s ±  1.769 s    [User: 876.089 s, System: 123.136 s]
    50  Range (min … max):   97.393 s … 103.823 s    20 runs
    

    And on a slowe2 i7 with HDD:

     0COMMITS="d767503b6a2618e0c99407acf98f3bd19fb7defd 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7 35e91b899dac689b24a8a95fcef083affc695d1e"; RUNS=20; CC=gcc; CXX=g++; BUILD='Release'; (echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && hyperfine   --sor
     1t command   --runs $RUNS   --parameter-list COMMIT ${COMMITS// /,}   --parameter-list FACTOR $(seq -s, 1 4)   --prepare "git checkout {COMMIT}; git clean -fxd; git reset --hard &&  cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${BUILD} && ninja -C build "   "build/test/functional/test_runner.py -j\$(({FACTOR} * $(nproc))) || true"                                           
     2                                                                                                                                                                                                                                                                                                                                                                                    
     3d767503b6a Merge bitcoin/bitcoin#33039: refactor,test: follow-ups to multi-byte block obfuscation                                                                                                                                                                                                                                                                                   
     45bb380ec87 test: sleep patch                                                                 
     535e91b899d test: Remove polling loop from test_runner                                        
     6
     7Benchmark 1: build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                                
     8  Time (mean ± σ):     536.561 s ± 10.213 s    [User: 741.217 s, System: 100.037 s]          
     9  Range (min … max):   518.267 s … 556.539 s    20 runs                                      
    10                                                                                             
    11Benchmark 2: build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                                
    12  Time (mean ± σ):     543.853 s ±  7.098 s    [User: 747.414 s, System: 100.004 s]
    13  Range (min … max):   532.029 s … 556.266 s    20 runs
    14                                                                                             
    15Benchmark 3: build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    16  Time (mean ± σ):     534.225 s ± 14.423 s    [User: 743.823 s, System: 100.001 s]
    17  Range (min … max):   502.162 s … 552.954 s    20 runs
    18                                                                                             
    19Benchmark 4: build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)
    20  Time (mean ± σ):     398.433 s ± 13.789 s    [User: 816.850 s, System: 108.760 s]
    21  Range (min … max):   368.803 s … 420.022 s    20 runs
    22                                                                                             
    23Benchmark 5: build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)
    24  Time (mean ± σ):     405.140 s ±  8.846 s    [User: 817.834 s, System: 109.110 s]
    25  Range (min … max):   388.287 s … 422.856 s    20 runs
    26                                                                                             
    27Benchmark 6: build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)
    28  Time (mean ± σ):     397.259 s ±  8.343 s    [User: 814.290 s, System: 108.749 s]
    29  Range (min … max):   378.060 s … 412.245 s    20 runs
    30                                                                                             
    31Benchmark 7: build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)     
    32  Time (mean ± σ):     351.179 s ±  8.515 s    [User: 855.037 s, System: 113.145 s]          
    33  Range (min … max):   336.721 s … 368.320 s    20 runs                                      
    34                                                                                             
    35Benchmark 8: build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                                
    36  Time (mean ± σ):     350.855 s ±  9.233 s    [User: 862.762 s, System: 113.541 s]          
    37  Range (min … max):   334.352 s … 366.530 s    20 runs                                      
    38                                                                                             
    39Benchmark 9: build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)                                                                
    40  Time (mean ± σ):     357.291 s ±  8.876 s    [User: 854.476 s, System: 114.151 s]          
    41  Range (min … max):   340.714 s … 369.699 s    20 runs                                      
    42                                                                                             
    43Benchmark 10: build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                               
    44  Time (mean ± σ):     338.878 s ±  5.938 s    [User: 881.142 s, System: 116.883 s]          
    45  Range (min … max):   328.316 s … 348.831 s    20 runs                                      
    46                                                                                             
    47Benchmark 11: build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                               
    48  Time (mean ± σ):     330.988 s ±  8.537 s    [User: 889.021 s, System: 116.644 s]          
    49  Range (min … max):   313.327 s … 344.076 s    20 runs                                      
    50                                                                                             
    51Benchmark 12: build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)                                                               
    52  Time (mean ± σ):     324.608 s ±  8.837 s    [User: 875.886 s, System: 116.579 s]          
    53  Range (min … max):   304.882 s … 341.161 s    20 runs                                      
    54                                                                                             
    55Relative speed comparison                                                                    
    56        1.65 ±  0.05  build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                       
    57        1.68 ±  0.05  build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                       
    58        1.65 ±  0.06  build/test/functional/test_runner.py -j$((1 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)                                                       
    59        1.23 ±  0.05  build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                       
    60        1.25 ±  0.04  build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                       
    61        1.22 ±  0.04  build/test/functional/test_runner.py -j$((2 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)                                                       
    62        1.08 ±  0.04  build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                       
    63        1.08 ±  0.04  build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                       
    64        1.10 ±  0.04  build/test/functional/test_runner.py -j$((3 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)                                                       
    65        1.04 ±  0.03  build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = d767503b6a2618e0c99407acf98f3bd19fb7defd)                                                       
    66        1.02 ±  0.04  build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = 5bb380ec87af93ed5543ba10e1f8465aca7bcfe7)                                                       
    67        1.00          build/test/functional/test_runner.py -j$((4 * 8)) || true (COMMIT = 35e91b899dac689b24a8a95fcef083affc695d1e)      
    

    Not sure we can claim that it’s faster, but makes more sense conceptually, maybe we can blow up the heavy tests and scale better.

  9. in test/functional/test_runner.py:762 in faaab70684 outdated
    760 
    761         dot_count = 0
    762         while True:
    763             # Return all procs that have finished, if any. Otherwise sleep until there is one.
    764-            time.sleep(.5)
    765+            procs = futures.wait(self.jobs, timeout=.5, return_when=futures.FIRST_COMPLETED)
    


    Eunovo commented at 10:10 am on August 15, 2025:
    https://github.com/bitcoin/bitcoin/pull/33141/commits/faaab70684779b81b2f6adac319bbf2d3b77165d: I thought the timeout here might be unnecessary, but I ran some benchmarks comparing .5s timeout to no timeout and this commit was always sligthly faster.

    maflcko commented at 1:23 pm on August 18, 2025:

    I ran some benchmarks comparing .5s timeout to no timeout and this commit was always sligthly faster.

    The reason why .5 is picked here is to preserve the observable behavior when print('.', end='', flush=True) is hit: During the sleep/wait you’ll only want a dot every half second, not in a busy-loop without delay. Using a busy-loop also sounds like a plausible explanation for your observed slow down, when decreasing it to 0.

    Other than that, I don’t think the exact value here should matter, as long as it is not zero.

  10. Eunovo commented at 10:11 am on August 15, 2025: contributor

    ACK https://github.com/bitcoin/bitcoin/pull/33141/commits/faaab70684779b81b2f6adac319bbf2d3b77165d

    I ran some simple benchmarks on my 8-core laptop

     0hyperfine \
     1--sort command \
     2--runs 3 \
     3--parameter-list COMMIT "master,faaab706" \
     4--prepare "git checkout {COMMIT}; cmake --build build -j 8" \
     5"build/test/functional/test_runner.py $(python3  -c "print('tool_wallet ' * 100)") -j 8"
     6Benchmark 1: build/test/functional/test_runner.py tool_wallet tool_wallet tool_wallet tool_wallet [...] tool_wallet  -j 8 (COMMIT = master)
     7  Time (mean ± σ):     107.620 s ±  1.261 s    [User: 568.243 s, System: 45.749 s]
     8  Range (min  max):   106.286 s  108.791 s    3 runs
     9 
    10Benchmark 2: build/test/functional/test_runner.py tool_wallet [...] tool_wallet  -j 8 (COMMIT = faaab706)
    11  Time (mean ± σ):     102.151 s ±  0.840 s    [User: 567.913 s, System: 45.192 s]
    12  Range (min  max):   101.257 s  102.925 s    3 runs
    13 
    14Relative speed comparison
    15        1.05 ±  0.02  build/test/functional/test_runner.py tool_wallet [...] tool_wallet  -j 8 (COMMIT = master)
    16        1.00          build/test/functional/test_runner.py tool_wallet [...] tool_wallet  -j 8 (COMMIT = faaab706)
    17
    18
    19hyperfine \                                          
    20--sort command \
    21--runs 3 \
    22--parameter-list COMMIT "master,faaab706" \
    23--prepare "git checkout {COMMIT}; cmake --build build -j 8" \
    24"build/test/functional/test_runner.py -j 8"
    25Benchmark 1: build/test/functional/test_runner.py -j 8 (COMMIT = master)
    26  Time (mean ± σ):     240.953 s ±  3.510 s    [User: 458.626 s, System: 96.167 s]
    27  Range (min  max):   238.456 s  244.967 s    3 runs
    28 
    29Benchmark 2: build/test/functional/test_runner.py -j 8 (COMMIT = faaab706)
    30  Time (mean ± σ):     232.209 s ± 10.131 s    [User: 441.218 s, System: 96.422 s]
    31  Range (min  max):   222.179 s  242.437 s    3 runs
    32 
    33Relative speed comparison
    34        1.04 ±  0.05  build/test/functional/test_runner.py -j 8 (COMMIT = master)
    35        1.00          build/test/functional/test_runner.py -j 8 (COMMIT = faaab706)
    

    https://github.com/bitcoin/bitcoin/pull/33141/commits/faaab70684779b81b2f6adac319bbf2d3b77165d is slightly faster in both cases.

  11. DrahtBot requested review from l0rinc on Aug 15, 2025
  12. maflcko removed review request from l0rinc on Aug 28, 2025
  13. maflcko requested review from l0rinc on Aug 28, 2025
  14. in test/functional/test_runner.py:750 in faaab70684 outdated
    759+            print("Remaining jobs: [{}]".format(", ".join(j.debug_name for j in self.jobs)))
    760 
    761         dot_count = 0
    762         while True:
    763             # Return all procs that have finished, if any. Otherwise sleep until there is one.
    764-            time.sleep(.5)
    


    l0rinc commented at 10:38 pm on August 29, 2025:
    Removing this changes the scheduling overlap to be more unpredictable since the new tasks will be scheduled immediately. That’s what we want it to do to avoid wasted cycles, but I can imagine this will result in new test failures we haven’t seen before.

    maflcko commented at 6:19 am on September 1, 2025:

    I can imagine this will result in new test failures we haven’t seen before.

    I’d doubt that test will fail due to scheduling them more tightly without sleeps in-between. Though, if they do, that is a good thing, because it hints at a bug that we should be aware of and ideally should fix.

  15. in test/functional/test_runner.py:765 in faaab70684 outdated
    768-            for job in self.jobs:
    769-                (name, start_time, proc, testdir, log_out, log_err) = job
    770-                if proc.poll() is not None:
    771+            for job in procs.done:
    772+                    (name, start_time, proc, testdir, log_out, log_err) = job.result()
    773                     log_out.seek(0), log_err.seek(0)
    


    l0rinc commented at 10:43 pm on August 29, 2025:
    what’s the reason for keeping the old indentation here?

    maflcko commented at 6:19 am on September 1, 2025:
    thx, formatted
  16. in test/functional/test_runner.py:709 in faaab70684 outdated
    703@@ -703,9 +704,9 @@ class TestHandler:
    704     """
    705     Trigger the test scripts passed in via the list.
    706     """
    707-
    708     def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control):
    709         assert num_tests_parallel >= 1
    710+        self.executor = futures.ThreadPoolExecutor(max_workers=num_tests_parallel)
    


    l0rinc commented at 10:49 pm on August 29, 2025:
    It’s likely not strictly needed, but if you edit again consider self.executor.shutdown(wait=True) once all tests are done

    maflcko commented at 6:10 am on September 1, 2025:

    Yeah, maybe. Though,

    • we can’t really use the return code anyway (there is none), so the only difference would be that we have to explicitly shutdown the executor somewhere.
    • There is no natural place to put it, because doing it in get_next seems confusing. Similarly, doing it before sys.exit seems like a layer violation.
    • putting an explicit shutdown somewhere is inconsistent, because the code path isn’t hit on exceptions (base exceptions)

    In practise it doesn’t matter, because if it is empty, no shutdown is needed and if it isn’t empty, a shutdown isn’t needed either, becaue python will wait on it anyway.

    leaving as-is for now.

  17. in test/functional/test_runner.py:743 in faaab70684 outdated
    740                               time.time(),
    741                               subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg,
    742                                                text=True,
    743                                                stdout=log_stdout,
    744-                                               stderr=log_stderr),
    745+                                               stderr=log_stderr,
    


    l0rinc commented at 10:51 pm on August 29, 2025:

    these extra commas make reformatted code look funny

    0                                 stderr=log_stderr,
    1                                 ),
    2                testdir,
    

    maflcko commented at 5:48 am on September 1, 2025:
    thx, formatted
  18. in test/functional/test_runner.py:769 in faaab70684 outdated
    773                     log_out.seek(0), log_err.seek(0)
    774                     [stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)]
    775                     log_out.close(), log_err.close()
    776                     skip_reason = None
    777-                    if proc.returncode == TEST_EXIT_PASSED and stderr == "":
    778+                    if proc == TEST_EXIT_PASSED and stderr == "":
    


    l0rinc commented at 10:55 pm on August 29, 2025:
    this is a bit confusing now, this isn’t the proc anymore, it’s the return value of the proc now

    maflcko commented at 6:20 am on September 1, 2025:
    thx, restored original code
  19. in test/functional/test_runner.py:738 in faaab70684 outdated
    734+            def proc_wait(task):
    735+                task[2] = task[2].wait()
    736+                return task
    737+
    738+            self.jobs.append(self.executor.submit(proc_wait, task=[
    739+                              test,
    


    l0rinc commented at 10:57 pm on August 29, 2025:
    formatting is off now that the leading ( was removed

    maflcko commented at 6:11 am on September 1, 2025:
    thx, ran formatter
  20. in test/functional/test_runner.py:734 in faaab70684 outdated
    728@@ -728,42 +729,50 @@ def get_next(self):
    729             test_argv = test.split()
    730             testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed)
    731             tmpdir_arg = ["--tmpdir={}".format(testdir)]
    732-            self.jobs.append((test,
    733+
    734+            def proc_wait(task):
    735+                task[2] = task[2].wait()
    


    l0rinc commented at 11:49 pm on August 29, 2025:

    I find this confusing - as mentioned below -, we’re replacing a value with a different typed one. Is the mutation strictly necessary or would something like

    0def proc_wait(task):
    1    name, start_time, proc, testdir, log_out, log_err = task
    2    return_code = proc.wait()
    3    return [name, start_time, return_code, testdir, log_out, log_err]
    

    also work?


    maflcko commented at 6:11 am on September 1, 2025:
    thx, kept the type
  21. l0rinc approved
  22. DrahtBot requested review from l0rinc on Aug 29, 2025
  23. test: Remove polling loop from test_runner fa7a3b5fb0
  24. maflcko force-pushed on Sep 1, 2025
  25. maflcko commented at 6:31 am on September 1, 2025: member
    force pushed with small formatting changes. Should be trivial to re-review via --ignore-all-space.
  26. in test/functional/test_runner.py:751 in fa7a3b5fb0
    755+                testdir,
    756+                log_stdout,
    757+                log_stderr,
    758+            ]
    759+            self.jobs.append(self.executor.submit(proc_wait, task))
    760+            self.jobs[-1].debug_name = test
    


    l0rinc commented at 5:30 pm on September 1, 2025:

    I’m not exactly sure how this works; my IDEs break here. Is my understanding correct that we’re just piggybacking a new value onto a Future’s per-instance __dict__? Would it be cleaner to use a Future-to-string dictionary instead?

    0self.job_name = {}
    1...
    2future = self.executor.submit(proc_wait, task)
    3self.job_name[future] = test
    4self.jobs.append(future)
    5...
    6print("Remaining jobs: [{}]".format(", ".join(self.job_name[f] for f in self.jobs)))
    

    (I checked, and it seems dicts are keyable by Futures, the Remaining jobs messages are the same this way)

    It’s also what the https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor-example is doing to connect the Futures back to their inputs

  27. in test/functional/test_runner.py:762 in fa7a3b5fb0
    768 
    769         dot_count = 0
    770         while True:
    771             # Return all procs that have finished, if any. Otherwise sleep until there is one.
    772-            time.sleep(.5)
    773+            procs = futures.wait(self.jobs, timeout=.5, return_when=futures.FIRST_COMPLETED)
    


    l0rinc commented at 5:33 pm on September 1, 2025:

    nit: since this is new code, maybe we could decompose done and not_done here already

    0done, not_done = futures.wait(self.jobs, timeout=.5, return_when=futures.FIRST_COMPLETED)
    1self.jobs = list(not_done)
    2ret = []
    3for fut in done:
    
  28. in test/functional/test_runner.py:761 in fa7a3b5fb0
    766-            print("Remaining jobs: [{}]".format(", ".join(j[0] for j in self.jobs)))
    767+            print("Remaining jobs: [{}]".format(", ".join(j.debug_name for j in self.jobs)))
    768 
    769         dot_count = 0
    770         while True:
    771             # Return all procs that have finished, if any. Otherwise sleep until there is one.
    


    l0rinc commented at 5:56 pm on September 1, 2025:
    is it still correct to claim that we’re sleeping?
  29. l0rinc approved
  30. l0rinc commented at 6:10 pm on September 1, 2025: contributor

    tested ACK fa7a3b5fb04465a3fbadf1ca62eac26827c1ef1d

    there are still a few things I’d prefer before we merge, but won’t block

  31. DrahtBot requested review from Eunovo on Sep 1, 2025

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: 2025-09-02 06:12 UTC

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