Skip to content

Conversation

@achow101
Copy link
Member

minEpochIterations is probably unnecessary to set, so removing it makes the runtime much faster.

This is probably unnecessary and just makes it slower.
@achow101
Copy link
Member Author

@fanquake Is this good enough or do you want faster? -unsafesqlitesync does not appear to have any effect. The next thing would be to reduce the number of txs created, but I'm concerned that doing so will make it harder to observe actual performance issues that this benchmark is intended to measure.

@maflcko
Copy link
Member

maflcko commented Apr 19, 2022

review ACK 9e404a9

@w0xlt
Copy link
Contributor

w0xlt commented Apr 19, 2022

On my machine:

Before PR #24913

Executed in   57.34 secs    fish           external
   usr time   57.60 secs  843.00 micros   57.60 secs
   sys time    1.43 secs    0.00 micros    1.43 secs

After PR #24913

|    1,525,136,424.90 |                0.66 |    0.2% |    189.67 | `WalletLoadingDescriptors`
|      873,902,969.45 |                1.14 |    0.3% |    106.20 | `WalletLoadingLegacy`

________________________________________________________
Executed in  564.01 secs    fish           external
   usr time  540.03 secs  427.00 micros  540.02 secs
   sys time   13.35 secs   95.00 micros   13.35 secs

This PR

|    1,740,638,493.00 |                0.57 |    0.6% |     26.13 | `WalletLoadingDescriptors`
|    1,016,725,382.00 |                0.98 |    0.9% |     12.72 | `WalletLoadingLegacy`

________________________________________________________
Executed in  348.35 secs    fish           external
   usr time  328.66 secs    1.05 millis  328.66 secs
   sys time   12.46 secs    0.60 millis   12.46 secs

There's a good improvement (348.35 secs) over PR #24913 (540.03 secs), but it still takes a lot longer than before it (57.34 secs).

@fanquake
Copy link
Member

@fanquake Is this good enough or do you want faster?

I think to be good enough, it needs to run in a similar time to all of the other benchmarks, i.e max ~1-2 seconds, otherwise anyone running make check on macOS is going to be opening issues asking why running make check (has suddenly started) taking 10+ minutes. I tested this branch, but stopped after WalletLoadingDescriptors took 12 minutes:

|           80,237.38 |           12,463.02 |    0.1% |      0.01 | `VerifyScriptBench`
|            8,190.91 |          122,086.52 |    1.2% |      0.01 | `WalletBalanceClean`
|          179,780.20 |            5,562.35 |    1.5% |      0.01 | `WalletBalanceDirty`
|            7,929.42 |          126,112.61 |    0.1% |      0.01 | `WalletBalanceMine`
|               42.47 |       23,546,683.62 |    0.0% |      0.01 | `WalletBalanceWatch`
|      902,283,977.00 |                1.11 |    1.4% |    105.48 | `WalletLoadingDescriptors`
^C
src/bench/bench_bitcoin  59.66s user 24.31s system 11% cpu 12:01.03 total

-unsafesqlitesync does not appear to have any effect. The next thing would be to reduce the number of txs created, but I'm concerned that doing so will make it harder to observe actual performance issues that this benchmark is intended to measure.

Given that, it seems like we've got another macOS only-performance issue, that we should probably figure out the root cause of?

@laanwj
Copy link
Member

laanwj commented Apr 20, 2022

I think to be good enough, it needs to run in a similar time to all of the other benchmarks, i.e max ~1-2 seconds,

Agree. It's unacceptable to have a benchmark take in the order of minutes. Remember that benchmarks are there to measure small timespans (such as inner loop functions), not very long processes.

I've also seen a CI timeout due to this. Remember that we do bench/bench_bitcoin &> /dev/null in one of the CI runs.

@achow101
Copy link
Member Author

I've added the following changes:

  • The number of benchmark epochs is reduced from the default 11 to 5.
  • Use unsafesqlitesync
  • Use mock databases
    • Update sqlite's mock database implementation to use in-memory dbs rather than just temp dbs
  • Instead of mining blocks to wallet addresses, we make transactions and add them directly with AddToWallet.
  • Reduced the number of txs added to the wallet from 5000 to 1000.

This still doesn't make it as fast as the other benchmarks though.


Before #24913:

________________________________________________________
Executed in   11.37 secs    fish           external
   usr time   11.36 secs    0.00 micros   11.36 secs
   sys time    7.62 secs  435.00 micros    7.62 secs

After #24913:

________________________________________________________
Executed in  150.77 secs    fish           external
   usr time  148.99 secs  334.00 micros  148.99 secs
   sys time    9.42 secs   88.00 micros    9.42 secs

This PR:

________________________________________________________
Executed in   20.25 secs    fish           external
   usr time   20.21 secs  319.00 micros   20.21 secs
   sys time    7.92 secs  158.00 micros    7.92 secs

@sipa
Copy link
Member

sipa commented May 10, 2022

This PR makes ./src/bench/bench_bitcoin -filter=WalletLoadingDescriptors go from taking 246s to 2.3s for me, making "make check" a lot more usable.

(Ubuntu 22.04 on a Ryzen 5950X system; my ZFS filesystem setup may make flushing/syncing relatively slower)

@maflcko
Copy link
Member

maflcko commented May 10, 2022

Looks like this also introduces memory corruption, looking at the CI output?

achow101 added 4 commits May 10, 2022 11:54
We may want to make a mock database of either SQLite or BDB, not just
whatever the compiled default is.
The mock db can be in-memory rather than just at temp file.
Using in-memory only databases speeds up the benchmark, at the cost of
real world accuracy.
Add descriptor wallet benchmark only if sqlite is compiled. Add legacy
wallet benchmark only if bdb is compiled.
@achow101 achow101 force-pushed the reduce-wallet-load-bench-runtime branch from 2b82a5e to e673d8b Compare May 10, 2022 15:54
@ajtowns
Copy link
Contributor

ajtowns commented May 10, 2022

Haven't reviewed the code at all, but e673d8b reduces the runtime of the WalletLoadingDescriptors test from 4m25s to 0.1s for me

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

Didn't look much at the code yet, but ran the benchmarks for both legacy and descriptor wallet on my (rather slow) system after each commit and master via

$ time ./src/bench/bench_bitcoin -filter=WalletLoadingLegacy
$ time ./src/bench/bench_bitcoin -filter=WalletLoadingDescriptors

with the following results:

Legacy Descriptors
master 3m18.39s 5m40.95s
Remove minEpochIterations (9e404a9) 1m54.15s 2m51.50s
use unsafesqlitesync (817c051) 1m53.68s 2m46.76s
reduce number of epochs (d94244c) 1m49.12s 2m38.29s
add txs directly instead of mining blocks (f85b54e) 1m27.61s 1m51.24s
reduce number of txs in wallet (7c0d344) 0m19.83s 0m27.06s
create mock db (a108080) 0m19.56s 0m26.18s
use in-memory db for mock db (49910f2) 0m19.36s 0m26.03s
use mock db (4af3547) 0m09.16s 0m07.25s
load bench depending on what's compiled (e673d8b) 0m09.51s 0m07.19s

Marked the commits in bold where the most gains (at least 2x) were observed. Looking closer at the descriptor wallet benchmark, if I (manually) revert commits 817c051 (using unsafesqlitesync) and 49910f2 (use in-memory mode for mock db) on the top commit via the patch

diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index f61138378..994811c79 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -85,7 +85,6 @@ static std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& dat
 static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet)
 {
     const auto test_setup = MakeNoLogFileContext<TestingSetup>();
-    test_setup->m_args.ForceSetArg("-unsafesqlitesync", "1");

     WalletContext context;
     context.args = &test_setup->m_args;
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 72d483e61..26908b377 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1203,7 +1203,7 @@ std::unique_ptr<WalletDatabase> CreateMockWalletDatabase(DatabaseOptions& option

     if (format == DatabaseFormat::SQLITE) {
 #ifdef USE_SQLITE
-        return std::make_unique<SQLiteDatabase>(":memory:", "", options, true);
+        return std::make_unique<SQLiteDatabase>("", "", options, true);
 #endif
         assert(false);
     }

and got a run-time of 0m07.41s. From that result, I'd conclude that commits 817c051 and 49910f2 barely have any effect on the run-time and could in theory be removed from this PR (no hard feelings though).

@hebasto hebasto mentioned this pull request May 21, 2022
@Rspigler
Copy link
Contributor

tACK e673d8b

This solves the make check issue with bench_bitcoin reported here

Copy link
Member

@furszy furszy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK e673d8b, nice PR.

With a note:
I think that we could keep generating a chain instead of adding the dummy txs directly, so the benchmark is more accurate to what happens in a real wallet (otherwise we are skipping some flows during the LoadToWallet(tx) process like the tx initial state update that requires a chain lookup).

What do you think about generating the chain manually instead of using the whole generatetoaddress flow, so we skip the entire BlockAssembler::CreateNewBlock, follow up TestBlockValidity, finding the correct nonce etc.. that are surely pretty slow.

As the wallet doesn't care about chain validity, we directly could: create, concatenate and append blocks into the chain index manually, which should be pretty fast, so the wallet can use them during the load flow.

wallet = BenchLoadWallet(std::move(database), context, options);

// Cleanup
database = DuplicateMockDatabase(wallet->GetDatabase(), options);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 4af3547:

I'm not so sure why do we need to update the database here, guess that what you wanted to do is rollback the db to the first mocked database created at line 103 and not the recently loaded one? So in case of any modification, we ensure that the benchmark is always running from the same static db input?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it's because deleting the wallet so that we can load it again will delete the database.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k, that is because of the db destructor, good.

@achow101
Copy link
Member Author

if I (manually) revert commits 817c051 (using unsafesqlitesync)

I think -unsafesqlitesync has more of an effect on macs than linux?

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK e673d8b. For each commit, verified that there was a performance improvement without negating the purpose of the bench, and made some effort to verify that the code is correct.

Would be nice to get this merged. I haven't used make check without quitting at bench in months :(

Nit: could you update the OP to include the list of things you've changed to make it run faster? It currently only mentions minEpochIterations.

if I (manually) revert commits 817c051 (using unsafesqlitesync)

I think -unsafesqlitesync has more of an effect on macs than linux?

Fwiw, I don't know exactly what -unsafesqlitesync does, but tried dropping the commit on my mac and ubuntu machines. It seems like neither had any change (specifically on my machines though, not sure about others).

#ifdef USE_BDB
return std::make_unique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(), "", options);
#endif
assert(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a108080 "walletdb: Create a mock database of specific type ": I hit this line in testing with both USE_SQLITE and USE_BDB off? I may have just messed something up, but does this need e673d8b "Enable loading benchmarks depending on what's compiled " squashed in?

@DrahtBot
Copy link
Contributor

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #25466 (ci: add unused-using-decls to clang-tidy by fanquake)

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.

@fanquake fanquake merged commit 480d806 into bitcoin:master Jun 28, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jun 29, 2022
e673d8b bench: Enable loading benchmarks depending on what's compiled (Andrew Chow)
4af3547 bench: Use mock wallet database for wallet loading benchmark (Andrew Chow)
49910f2 sqlite: Use in-memory db instead of temp for mockdb (Andrew Chow)
a108080 walletdb: Create a mock database of specific type (Andrew Chow)
7c0d344 bench: reduce the number of txs in wallet for wallet loading bench (Andrew Chow)
f85b54e bench: Add transactions directly instead of mining blocks (Andrew Chow)
d94244c bench: reduce number of epochs for wallet loading benchmark (Andrew Chow)
817c051 bench: use unsafesqlitesync in wallet loading benchmark (Andrew Chow)
9e404a9 bench: Remove minEpochIterations from wallet loading benchmark (Andrew Chow)

Pull request description:

  `minEpochIterations` is probably unnecessary to set, so removing it makes the runtime much faster.

ACKs for top commit:
  Rspigler:
    tACK e673d8b
  furszy:
    Code review ACK e673d8b, nice PR.
  glozow:
    Concept ACK e673d8b. For each commit, verified that there was a performance improvement without negating the purpose of the bench, and made some effort to verify that the code is correct.

Tree-SHA512: 9337352ef846cf18642d5c14546c5abc1674b4975adb5dc961a1a276ca91f046b83b7a5e27ea6cd26264b96ae71151e14055579baf36afae7692ef4029800877
@bitcoin bitcoin locked and limited conversation to collaborators Jun 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.