wallet, bench: Use Nanobench setup() for wallet benchmarks, and remove DuplicateMockDatabase #35018

pull achow101 wants to merge 6 commits into bitcoin:master from achow101:wallet-bench-setups changing 7 files +122 −123
  1. achow101 commented at 10:22 PM on April 6, 2026: member

    Several of the wallet benchmarks have some setup or cleanup that needs to be done per run. Now that #34208 is merged, these can use setup(). Additionally, this allows for removing DuplicateMockDatabase in WalletEncryptDescriptors.

    This PR also removes DuplicateMockDatabase in WalletLoadingDescriptors. DuplicateMockDatabase was added here in #24924 as part of benchmark performance improvements. However, it does not appear to make a significant difference today.

    Removing DuplicateMockDatabase makes future database changes easier. In particular it should simplify #33032 and #33034, and any future changes that introduce sqlite features.

  2. DrahtBot commented at 10:22 PM on April 6, 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.

    Type Reviewers
    ACK l0rinc, furszy
    Concept ACK davidgumberg, theStack

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33034 (wallet: Store transactions in a separate sqlite table by achow101)
    • #25722 (refactor: Use util::Result class for wallet loading by ryanofsky)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. DrahtBot added the label CI failed on Apr 6, 2026
  4. davidgumberg commented at 12:23 AM on April 7, 2026: contributor

    Concept ACK

  5. achow101 force-pushed on Apr 7, 2026
  6. in src/bench/wallet_encrypt.cpp:41 in bedfbe9033 outdated
      73 | -        TestUnloadWallet(std::move(wallet));
      74 | -    });
      75 | +    std::unique_ptr<WalletDatabase> database;
      76 | +    std::shared_ptr<CWallet> wallet;
      77 | +    bench.batch(key_count).unit("key").setup([&] {
      78 | +            if (wallet) {
    


    davidgumberg commented at 1:19 AM on April 10, 2026:

    nit: too deeply indented?


    achow101 commented at 7:35 PM on April 20, 2026:

    Fixed

  7. davidgumberg commented at 1:34 AM on April 10, 2026: contributor

    I believe the reason for CI failure is that you need to set epochIterations=1 since the setup is only run once per epoch, and an epoch might have more than one iteration.

  8. in src/bench/wallet_balance.cpp:55 in 35a5b7e5c5
      51 | @@ -52,11 +52,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
      52 |  
      53 |      auto bal = GetBalance(wallet); // Cache
      54 |  
      55 | -    bench.run([&] {
      56 | -        if (set_dirty) wallet.MarkDirty();
      57 | -        bal = GetBalance(wallet);
      58 | -        if (add_mine) assert(bal.m_mine_trusted > 0);
      59 | -    });
      60 | +    bench.setup([&] {
    


    davidgumberg commented at 1:48 AM on April 10, 2026:
        bench.epochIterations(1).setup([&] {
    

    here and elsewhere


    l0rinc commented at 12:10 PM on April 10, 2026:

    you need to set epochIterations=1 since the setup is only run once per epoch

    Yes, I will add a new PR to make sure this is asserted in the new setup and explained in the error.

    Nanobench has two iterations for better signal-to-noise ratio (framework cost vs measured code). But if we apply a setup phase, we admit that the benchmark is heavy and the framework won't overshadow the actual measurement (e.g. compared to the cost of an i++, running a lambda can be costly). That's not the case here, so we disable epoch iterations and only leave the 11 default epochs for stability.

    diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
    index eab3f13d86..75022ee4db 100644
    --- a/src/bench/wallet_balance.cpp
    +++ b/src/bench/wallet_balance.cpp
    @@ -53,9 +53,8 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
     
         auto bal = GetBalance(wallet); // Cache
     
    -    bench.setup([&] {
    -            if (set_dirty) wallet.MarkDirty();
    -        })
    +    bench.epochIterations(1)
    +        .setup([&] { if (set_dirty) wallet.MarkDirty(); })
             .run([&] {
                 bal = GetBalance(wallet);
                 if (add_mine) assert(bal.m_mine_trusted > 0);
    diff --git a/src/bench/wallet_create.cpp b/src/bench/wallet_create.cpp
    index 990bfdf006..615bb049dc 100644
    --- a/src/bench/wallet_create.cpp
    +++ b/src/bench/wallet_create.cpp
    @@ -48,7 +48,8 @@ static void WalletCreate(benchmark::Bench& bench, bool encrypted)
         const auto wallet_name = fs::PathToString(wallet_path);
     
         std::shared_ptr<CWallet> wallet;
    -    bench.setup([&] {
    +    bench.epochIterations(1)
    +        .setup([&] {
                 if (wallet) {
                     // Release wallet
                     RemoveWallet(context, wallet, /*load_on_start=*/ std::nullopt);
    diff --git a/src/bench/wallet_encrypt.cpp b/src/bench/wallet_encrypt.cpp
    index e1ffc18a01..971a7797c8 100644
    --- a/src/bench/wallet_encrypt.cpp
    +++ b/src/bench/wallet_encrypt.cpp
    @@ -37,7 +37,8 @@ static void WalletEncrypt(benchmark::Bench& bench, unsigned int key_count)
     
         std::unique_ptr<WalletDatabase> database;
         std::shared_ptr<CWallet> wallet;
    -    bench.batch(key_count).unit("key").setup([&] {
    +    bench.batch(key_count).unit("key").epochIterations(1)
    +        .setup([&] {
                 if (wallet) {
                     TestUnloadWallet(std::move(wallet));
                 }
    @@ -63,7 +64,6 @@ static void WalletEncrypt(benchmark::Bench& bench, unsigned int key_count)
                 for (const auto& [_, key] : wallet->mapMasterKeys){
                     assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
                 }
    -
             });
     }
     
    diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
    index 0ac6006ec1..f7d9012caf 100644
    --- a/src/bench/wallet_loading.cpp
    +++ b/src/bench/wallet_loading.cpp
    @@ -58,7 +58,8 @@ static void WalletLoadingDescriptors(benchmark::Bench& bench)
         options.require_create = false;
         options.require_existing = true;
     
    -    bench.epochs(5).setup([&] {
    +    bench.epochs(5).epochIterations(1)
    +        .setup([&] {
                 TestUnloadWallet(std::move(wallet));
                 database = MakeWalletDatabase("", options, status, error);
             })
    
    

    achow101 commented at 7:36 PM on April 20, 2026:

    Done

  9. in src/bench/wallet_balance.cpp:59 in bedfbe9033 outdated
      59 | -    });
      60 | +    bench.setup([&] {
      61 | +            if (set_dirty) wallet.MarkDirty();
      62 | +        })
      63 | +        .run([&] {
      64 | +            bal = GetBalance(wallet);
    


    l0rinc commented at 10:16 AM on April 10, 2026:

    What's the reason for assigning externally?

                const auto bal{GetBalance(wallet)};
    

    achow101 commented at 7:27 PM on April 20, 2026:

    There's no particular reason for assigning it externally, but running GetBalance outside of the benchmark is necessary for benchmarks that expect the balances to already be cached.

  10. in src/bench/wallet_balance.cpp:65 in bedfbe9033


    l0rinc commented at 12:11 PM on April 10, 2026:

    What's the difference between WalletBalanceClean and WalletBalanceMine?


    l0rinc commented at 2:49 PM on April 20, 2026:

    achow101 commented at 7:32 PM on April 20, 2026:

    This is a holdover from legacy wallet. There used to be a third parameter.


    l0rinc commented at 8:49 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    This commit is quite complicated, mixing changes in different files in different ways. To ease the review process it might help to split them by benchmark, e.g.

    • bench: prepare migration wallet in setup
    • bench: prepare encryption wallets in setup
    • bench: clean wallet create outside timing
    • bench: isolate wallet balance measurement

    and explain the gist of the change in each commit message. It's not a blocker from me of course, I just have a hard time fully understanding every single change here.

  11. in src/bench/wallet_balance.cpp:60 in bedfbe9033 outdated
      60 | +    bench.setup([&] {
      61 | +            if (set_dirty) wallet.MarkDirty();
      62 | +        })
      63 | +        .run([&] {
      64 | +            bal = GetBalance(wallet);
      65 | +            if (add_mine) assert(bal.m_mine_trusted > 0);
    


    l0rinc commented at 12:13 PM on April 10, 2026:

    note: we should always assert or ankerl::nanobench::doNotOptimizeAway the result to avoid the compiler getting rid of the calculation.


    achow101 commented at 7:36 PM on April 20, 2026:

    done

  12. theStack commented at 5:32 PM on April 14, 2026: contributor

    Concept ACK

  13. DrahtBot added the label Needs rebase on Apr 19, 2026
  14. achow101 force-pushed on Apr 20, 2026
  15. achow101 force-pushed on Apr 20, 2026
  16. DrahtBot removed the label Needs rebase on Apr 20, 2026
  17. DrahtBot removed the label CI failed on Apr 20, 2026
  18. in src/bench/wallet_encrypt.cpp:57 in fed630547f
      89 | +                    CKey key = GenerateRandomKey();
      90 | +                    FlatSigningProvider keys;
      91 | +                    std::string error;
      92 | +                    std::vector<std::unique_ptr<Descriptor>> desc = Parse("combo(" + EncodeSecret(key) + ")", keys, error, /*require_checksum=*/false);
      93 | +                    WalletDescriptor w_desc(std::move(desc.at(0)), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/0, /*next_index=*/0);
      94 | +                    Assert(wallet->AddWalletDescriptor(w_desc, keys, /*label=*/"", /*internal=*/false));
    


    furszy commented at 12:03 AM on April 21, 2026:

    Could cache the descriptors outside the setup function. GenerateRandomKey() uses GetStrongRandBytes, which is not free.

    Same for the wallet_migration benchmark. It would be good to have objects that can be re-utilized constructed only once.


    achow101 commented at 7:48 PM on April 27, 2026:

    Done

  19. fanquake referenced this in commit 2d5ab09f0d on Apr 24, 2026
  20. achow101 force-pushed on Apr 27, 2026
  21. sedited requested review from l0rinc on Apr 27, 2026
  22. sedited requested review from davidgumberg on Apr 27, 2026
  23. DrahtBot added the label CI failed on Apr 27, 2026
  24. DrahtBot commented at 8:35 PM on April 27, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task tidy: https://github.com/bitcoin/bitcoin/actions/runs/25015977398/job/73263792269</sub> <sub>LLM reason (✨ experimental): CI failed because clang-tidy reported a performance-inefficient-vector-operation warning treated as an error: keys.push_back(...) was called inside a loop in bench/wallet_migration.cpp.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  25. achow101 force-pushed on Apr 28, 2026
  26. in src/bench/wallet_balance.cpp:56 in d9e4fd8656
      52 | @@ -53,18 +53,24 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
      53 |  
      54 |      auto bal = GetBalance(wallet); // Cache
      55 |  
      56 | -    bench.run([&] {
      57 | -        if (set_dirty) wallet.MarkDirty();
      58 | -        bal = GetBalance(wallet);
      59 | -        if (add_mine) assert(bal.m_mine_trusted > 0);
      60 | -    });
      61 | +    bench.epochIterations(1)
    


    l0rinc commented at 6:42 PM on April 28, 2026:

    Following the review here the epochIterations aren't needed anymore, see: https://github.com/bitcoin/bitcoin/commit/e6430b2773436c65d447fff5e0a326087abc4950


    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  27. in src/bench/wallet_create.cpp:55 in d9e4fd8656
      54 | +    std::shared_ptr<CWallet> wallet;
      55 | +    bench.epochIterations(1)
      56 | +        .setup([&] {
      57 | +            if (wallet) {
      58 | +                // Release wallet
      59 | +                RemoveWallet(context, wallet, /*load_on_start=*/ std::nullopt);
    


    l0rinc commented at 6:43 PM on April 28, 2026:

    nit:

                    RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt);
    

    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  28. DrahtBot removed the label CI failed on Apr 28, 2026
  29. in src/bench/wallet_balance.cpp:63 in f2db6d6c42
      63 | +            if (set_dirty) wallet.MarkDirty();
      64 | +        })
      65 | +        .run([&] {
      66 | +            bal = GetBalance(wallet);
      67 | +            ankerl::nanobench::doNotOptimizeAway(bal);
      68 | +            if (add_mine) assert(bal.m_mine_trusted > 0);
    


    l0rinc commented at 8:31 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Could we always assert something about the outcome - even when add_mine is false, e.g.

                assert(add_mine == (bal.m_mine_trusted > 0));
    

    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  30. in src/bench/wallet_create.cpp:69 in f2db6d6c42
      74 | -        fs::remove(wallet_path / "wallet.dat");
      75 | -        fs::remove(wallet_path);
      76 | -    });
      77 | +    // Cleanup
      78 | +    RemoveWallet(context, wallet, /*load_on_start=*/ std::nullopt);
      79 | +    WaitForDeleteWallet(std::move(wallet));
    


    l0rinc commented at 8:38 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Since we're doing part of the cleanup at the end anyway, it may make sense to extract the cleanup to a lambda that would be executed both during setup and at the end, something like:

    std::shared_ptr<CWallet> wallet;
    auto cleanup_wallet{[&] {
        if (!wallet) return;
        RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt);
        WaitForDeleteWallet(std::move(wallet));
        fs::remove(wallet_path / "wallet.dat");
        fs::remove(wallet_path);
    }};
    bench.setup(cleanup_wallet).run([&] {
        wallet = CreateWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error_string, warnings);
        assert(status == DatabaseStatus::SUCCESS);
        assert(wallet != nullptr);
    });
    cleanup_wallet();
    

    nit: same formatting inconsistency


    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  31. in src/bench/wallet_encrypt.cpp:72 in f2db6d6c42
     103 | +            wallet->EncryptWallet(secure_pass);
     104 | +
     105 | +            for (const auto& [_, key] : wallet->mapMasterKeys){
     106 | +                assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
     107 | +            }
     108 | +
    


    l0rinc commented at 8:40 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Similarly to other benchmarks (where the setup does a similar cleanup at the end) we could unload the last wallet after the benchmark finishes, something like:

            .run([&] {
                wallet->EncryptWallet(secure_pass);
    
                for (const auto& [_, key] : wallet->mapMasterKeys){
                    assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
                }
            });
        TestUnloadWallet(std::move(wallet));
    

    super-nit: extra line


    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  32. in src/bench/wallet_migration.cpp:43 in f2db6d6c42
      43 | +    // Generate transactions and local addresses
      44 | +    std::vector<CKey> keys;
      45 | +    keys.reserve(500);
      46 | +    for (int j = 0; j < 500; ++j) {
      47 | +        keys.push_back(GenerateRandomKey());
      48 | +    }
    


    l0rinc commented at 8:50 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Alternatively, we might be able to simplify (and deduplicate) this to something like:

    std::vector<CKey> keys(500);
    std::ranges::generate(keys, [] { return GenerateRandomKey(); });
    

    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  33. in src/bench/wallet_encrypt.cpp:34 in f2db6d6c42 outdated
      47 | -
      48 | -    database = DuplicateMockDatabase(wallet->GetDatabase());
      49 |  
      50 | -    // reload the wallet for the actual benchmark
      51 | -    TestUnloadWallet(std::move(wallet));
      52 | +    std::vector<std::pair<WalletDescriptor, FlatSigningProvider>> descs;
    


    l0rinc commented at 8:54 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Given that we know the expected size of this vector we could reserve it in advance:

        descs.reserve(key_count);
    

    achow101 commented at 9:54 PM on April 29, 2026:

    Done

  34. in src/wallet/test/util.cpp:119 in d9e4fd8656 outdated
     114 | -    std::unique_ptr<DatabaseBatch> new_db_batch = new_db->MakeBatch();
     115 | -    MockableSQLiteBatch* batch_new = dynamic_cast<MockableSQLiteBatch*>(new_db_batch.get());
     116 | -    Assert(batch_new);
     117 | -
     118 | -    while (true) {
     119 | -        DataStream key, value;
    


    l0rinc commented at 8:55 AM on April 29, 2026:

    d9e4fd8 wallet, test: Remove DuplicateMockDatabase:

    It seems to me we don't need the streams.h include after this removal anymore


    achow101 commented at 9:55 PM on April 29, 2026:

    Removed

  35. in src/bench/wallet_encrypt.cpp:57 in f2db6d6c42
      88 | +            if (wallet) {
      89 | +                TestUnloadWallet(std::move(wallet));
      90 | +            }
      91 | +
      92 | +            database = CreateMockableWalletDatabase();
      93 | +            wallet = TestCreateWallet(std::move(database), context, create_flags);
    


    l0rinc commented at 9:06 AM on April 29, 2026:

    f2db6d6 bench: Use nanobench setup api in wallet benchmarks:

    Do we need to expose database here or could we inline it for simplicity:

                wallet = TestCreateWallet(CreateMockableWalletDatabase(), context, create_flags);
    

    achow101 commented at 9:55 PM on April 29, 2026:

    Done

  36. l0rinc approved
  37. l0rinc commented at 9:36 AM on April 29, 2026: contributor

    Overall the direction looks correct, concept ACK.

    Left a few comments mostly about small robustness/readability follow-ups around cleanup symmetry, benchmark invariants, final unloads, etc. The only broader suggestion was splitting the first commit by benchmark (and explaining it in the message) to make review easier - since I had a hard time reviewing that meaningfully.

  38. bench: Utilize setup() in WalletCreate to cleanup previous wallets
    The WalletCreate benchmark should only be for creating a wallet and
    exclude the unloading of the newly created wallet. Instead, unloading
    can be done in setup() and after the benchmark completes.
    61412ef887
  39. bench: Utilitze setup() in WalletBalance for marking caches dirty
    WalletBalance benchmarks the balance computation function and should
    exclude the setup step of (optionally) marking caches as dirty. Instead,
    that is moved into setup().
    d672455d20
  40. bench: Utilize setup() in WalletEncrypt to create the encryption wallet
    WalletEncrypt needs an unencrypted wallet in order for the benchmark to
    encrypt a wallet. This was previously achieved by duplicating the
    contents of an initial wallet for each run of the benchmark. We can
    instead use setup() to unload the previously loaded wallet and then
    create a new wallet with unencrypted keys.
    426a94e7bd
  41. bench: Use setup() in WalletMigration to prepare the legacy wallet
    WalletMigration needs a new wallet with legacy records for each run of
    the benchmark. This can be done in setup() rather than duplicating the
    records of an initial wallet.
    9a7604fd25
  42. bench: Utilize setup() for WalletLoading and use a real database
    Instead of making a mock database and duplicating it for the benchmark,
    use a real database. Also use setup() to avoid measuring the overhead in
    the benchmark.
    57820c472b
  43. achow101 force-pushed on Apr 29, 2026
  44. wallet, test: Remove DuplicateMockDatabase
    DuplicateMockDatabase is no longer used. Furthermore, as SQLite gets
    used more as a database and less as a key value store, this function
    gets more complicated and more bug prone. As the benchmarks now run
    equivalently quickly with a real database, retaining this duplication
    function is no longer necessary.
    1d1ae6f0c4
  45. achow101 force-pushed on Apr 29, 2026
  46. achow101 commented at 9:55 PM on April 29, 2026: member

    Split the first commit to be per benchmark and with more explanation.

  47. DrahtBot added the label CI failed on Apr 29, 2026
  48. DrahtBot removed the label CI failed on Apr 29, 2026
  49. in src/bench/wallet_encrypt.cpp:49 in 426a94e7bd
      79 | -            assert(key.nDeriveIterations == CMasterKey::DEFAULT_DERIVE_ITERATIONS);
      80 | -        }
      81 | -
      82 | -        TestUnloadWallet(std::move(wallet));
      83 | -    });
      84 | +    std::unique_ptr<WalletDatabase> database;
    


    l0rinc commented at 6:31 AM on April 30, 2026:

    426a94e bench: Utilize setup() in WalletEncrypt to create the encryption wallet:

    We should be able to remove it now

  50. in src/bench/wallet_balance.cpp:61 in d672455d20
      61 | +    bench.setup([&] {
      62 | +            if (set_dirty) wallet.MarkDirty();
      63 | +        })
      64 | +        .run([&] {
      65 | +            bal = GetBalance(wallet);
      66 | +            ankerl::nanobench::doNotOptimizeAway(bal);
    


    l0rinc commented at 6:48 AM on April 30, 2026:

    d672455 bench: Utilitze setup() in WalletBalance for marking caches dirty:

    Now that bal is always used, we probably don't need the doNotOptimizeAway anymore since the compiler can't (easily) cheat

  51. in src/bench/wallet_migration.cpp:32 in 9a7604fd25
      32 | -    {
      33 | -        LegacyDataSPKM* legacy_spkm = wallet->GetOrCreateLegacyDataSPKM();
      34 | -        WalletBatch batch{wallet->GetDatabase()};
      35 | +    // Add watch-only addresses
      36 | +    std::vector<std::pair<CScript, CTxDestination>> scripts_watch_only;
      37 | +    for (int w = 0; w < NUM_WATCH_ONLY_ADDR; ++w) {
    


    l0rinc commented at 7:14 AM on April 30, 2026:

    9a7604f bench: Use setup() in WalletMigration to prepare the legacy wallet:

    scripts_watch_only could also be reserved:

    scripts_watch_only.reserve(NUM_WATCH_ONLY_ADDR);
    
  52. in src/bench/wallet_migration.cpp:44 in 9a7604fd25
      47 | -        // Write a best block record as migration expects one to exist
      48 | -        CBlockLocator loc;
      49 | -        batch.WriteBestBlock(loc);
      50 | +    std::unique_ptr<CWallet> wallet;
      51 | +    size_t i = 0;
      52 | +    bench.epochs(/*numEpochs=*/1) // run the migration exactly once
    


    l0rinc commented at 7:18 AM on April 30, 2026:

    9a7604f bench: Use setup() in WalletMigration to prepare the legacy wallet:

    nit: I think it should technically be safe now to remove the explicit single epoch limitation.

  53. in src/bench/wallet_loading.cpp:58 in 57820c472b
      55 |      for (int i = 0; i < 1000; ++i) {
      56 |          AddTx(*wallet);
      57 |      }
      58 |  
      59 | -    database = DuplicateMockDatabase(wallet->GetDatabase());
      60 | +    options.require_create = false;
    


    l0rinc commented at 7:23 AM on April 30, 2026:

    57820c4 bench: Utilize setup() for WalletLoading and use a real database:

    Nit: a brief comment might make it explicit that we're overwriting an explicit previous assignment here: // Switching to loading the existing database after initial creation

  54. in src/bench/wallet_migration.cpp:40 in 9a7604fd25
      40 | +        scripts_watch_only.emplace_back(GetScriptForDestination(dest), dest);
      41 | +    }
      42 | +
      43 | +    // Generate transactions and local addresses
      44 | +    std::vector<CKey> keys(500);
      45 | +    std::ranges::generate(keys, []{ return GenerateRandomKey(); });
    


    l0rinc commented at 7:26 AM on April 30, 2026:

    9a7604f bench: Use setup() in WalletMigration to prepare the legacy wallet:

    nit: we might want to add #include <algorithm> now

  55. l0rinc approved
  56. l0rinc commented at 7:28 AM on April 30, 2026: contributor

    code review ACK 1d1ae6f0c4f2f60f5ceb2d60e8a52662e542e21d

    I left some nits, happy to reack if applied. Changes look good otherwise.

  57. DrahtBot requested review from theStack on Apr 30, 2026
  58. achow101 commented at 5:46 PM on April 30, 2026: member

    Will do nits if I need to retouch.

  59. in src/bench/wallet_encrypt.cpp:65 in 426a94e7bd
      69 | -    // https://github.com/bitcoin/bitcoin/pull/34208 is merged.
      70 | -    bench.batch(key_count).unit("key").run([&] {
      71 | -        wallet = TestLoadWallet(std::move(database), context);
      72 | -
      73 | -        // Save a copy of the db before encrypting
      74 | -        database = DuplicateMockDatabase(wallet->GetDatabase());
    


    furszy commented at 6:26 PM on April 30, 2026:

    q: have you thought about using SQLiteDatabase::Backup to create an in-memory copy of the db? (move the method to use sqlite3_open_v2 and provide SQLITE_OPEN_MEMORY)

    Or adding a new SQLiteDatabase::Copy in order to wrap the in-memory sqlite3 copy into a SQLiteDatabase object?

    If you don't want to spend time here is fine as well. Just thinking out loud, in case want to avoid doing the AddWalletDescriptor repetitive work.


    achow101 commented at 8:25 PM on April 30, 2026:

    might want to do that eventually, but not here.

  60. in src/bench/wallet_loading.cpp:64 in 57820c472b
      66 | -    bench.epochs(5).run([&] {
      67 | -        wallet = TestLoadWallet(std::move(database), context);
      68 | +    bench.epochs(5)
      69 | +        .setup([&] {
      70 | +            TestUnloadWallet(std::move(wallet));
      71 | +            database = MakeWalletDatabase("", options, status, error);
    


    furszy commented at 10:40 PM on April 30, 2026:

    nano nit: could assert this opens the db with the 1k txs

  61. in src/bench/wallet_loading.cpp:55 in 57820c472b
      51 | +    auto database = MakeWalletDatabase("", options, status, error);
      52 |      auto wallet = TestCreateWallet(std::move(database), context, create_flags);
      53 |  
      54 |      // Generate a bunch of transactions and addresses to put into the wallet
      55 |      for (int i = 0; i < 1000; ++i) {
      56 |          AddTx(*wallet);
    


    furszy commented at 10:41 PM on April 30, 2026:

    Now we will write to disk 1k times. it would be good to batch it in the future.

  62. in src/bench/wallet_loading.cpp:71 in 57820c472b
      77 | -        // Cleanup
      78 | -        database = DuplicateMockDatabase(wallet->GetDatabase());
      79 | -        TestUnloadWallet(std::move(wallet));
      80 | -    });
      81 | +    // Cleanup
      82 | +    TestUnloadWallet(std::move(wallet));
    


    furszy commented at 10:43 PM on April 30, 2026:

    This makes me think that it would be nice to have a teardown function in the benchmark framework.

  63. furszy commented at 10:48 PM on April 30, 2026: member

    I'm not finding 9a7604fd257c4a549d0f22f28a36fef607c0dcf4 particularly useful, the benchmark still run migration just once and the change is not needed for the DuplicateMockDatabase removal. Would just drop the commit for now.

    Other than that, ACK 1d1ae6f0c4f2f60f5ceb2d60e8a52662e542e21d


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-05-01 03:13 UTC

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