achow101
commented at 9:16 pm on September 18, 2019:
member
For large wallets with many transactions and keys, inserting and fetching from a std::map can have a performance impact. Since we largely do not rely on the sorting properties of std::map, we can use std::unordered_map instead which is a hash table and insertion and retrieval are constant time. We also use std::unordered_multimap for some things that were std::multimap.
The changed maps are:
mapWallet: Map of all transactions
mapTxSpends: Map of outpoints to the txids of the txs that spent them
*mapKeyMetadata: Map of key metadata
*mapScriptMetadata: Map of script metadata
*mapKeys: Map of private keys
*mapCryptedKeys: Map of encrypted private keys
*mapWatchKeys: Set of watch only keys.
*setWatchOnly: Set of watch only scripts (std::unordered_set, not a map)
Change mapWallet and mapTxSpends did require a few other changes and thus they are in their own commits. Additionally, the GUI relied on getting transactions from the wallet in a sorted order which unordered_map does not provide, so the commit “Change getWalletTxs to return a set instead of a vector” is needed in order to put all of the txs into a std::set (which is ordered) instead of a vector in order to retain the same behavior.
mapTxSpends also relied on the sorted order to have some quick lookups, but these were changed to just do normal lookups over the same thing. It should be just as fast, or even faster, since std::unordered_map is a hash table.
The hash function used for these unordered maps and sets is SipHash, using the SipHash module that we already have. SaltedTxidHasher and SaltedOutPointHasher were moved from their original locations in utxo set and validation code in order to also be used from the wallet. Additionally SaltedIDHasher was added to hash uint160s (i.e. CKeyID and CScriptID) and SaltedScriptHasher was added to hash CScripts.
I did some becnhmarks with a large wallet I created on regtest using this script. This wallet is 169 MB in size with 117035 transactions and 103264 keys. It took ~20 secs to load on master, and ~18 secs with this change. So this change reduces wallet loading time by ~10%.
DrahtBot added the label
Mempool
on Sep 18, 2019
DrahtBot added the label
Tests
on Sep 18, 2019
DrahtBot added the label
UTXO Db and Indexes
on Sep 18, 2019
DrahtBot added the label
Wallet
on Sep 18, 2019
achow101 force-pushed
on Sep 18, 2019
achow101
commented at 9:36 pm on September 18, 2019:
member
Shuffled some things around to get rid of the circular dependency. Also fixed a typo
promag
commented at 9:47 pm on September 18, 2019:
member
Concept ACK, especially improvements targeting big wallets (either lots of keys or lots of transactions).
jonatack
commented at 9:50 pm on September 18, 2019:
member
Concept ACK, will review and run valgrind+massif visualizer and flamegraphs to compare. Anywhere we can get a big wallet file? EDIT: Saw the script you posted in the PR body above… running.
achow101
commented at 10:09 pm on September 18, 2019:
member
Massif (heap profiler) memory usage over time on master:
Massif memory usage over time on this PR:
in
src/wallet/wallet.cpp:752
in
4ed9dd6ffboutdated
748@@ -749,7 +749,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
749 bool CWallet::HasWalletSpend(const uint256& txid) const
750 {
751 AssertLockHeld(cs_wallet);
752- auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
753+ auto iter = mapTxSpends.find(COutPoint(txid, 0));
ryanofsky
commented at 11:27 pm on September 18, 2019:
Looks like a bug here. Previously it would return true if any output was spent, now it will only return true if the first output was spent. Could fix pretty easily by passing const CTransaction& instead of txid, and looping over the outputs.
achow101
commented at 0:31 am on September 19, 2019:
Looks like a bug here. Previously it would return true if any output was spent, now it will only return true if the first output was spent. Could fix pretty easily by passing const CTransaction& instead of txid, and looping over the outputs.
A suggestion for a followup: it could be useful to add a test for it to prevent regressions in the future.
achow101 force-pushed
on Sep 19, 2019
achow101 force-pushed
on Sep 19, 2019
achow101 force-pushed
on Sep 19, 2019
achow101 force-pushed
on Sep 19, 2019
fanquake removed the label
Tests
on Sep 19, 2019
DrahtBot
commented at 0:55 am on September 19, 2019:
member
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Conflicts
Reviewers, this pull request conflicts with the following ones:
#19671 (wallet: Remove -zapwallettxes by achow101)
#19653 (wallet: Replace -zapwallettxes with zapwallettxes RPC by achow101)
#19289 (wallet: GetWalletTx and IsMine require cs_wallet lock by promag)
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.
achow101
commented at 10:11 pm on September 19, 2019:
member
I did 1000 runs of my wallet loading benchmark. The mean loading time on master was 18408.14423 ms and the mean loading time on with this PR was 17498.71984. This is ~1 second faster, which is a ~5% performance increase with this PR. I also did a 2 sample t-test to check that these results are statistically significant, and it appears that they are.
achow101 force-pushed
on Sep 19, 2019
DrahtBot added the label
Needs rebase
on Sep 30, 2019
achow101 force-pushed
on Sep 30, 2019
DrahtBot removed the label
Needs rebase
on Sep 30, 2019
laanwj added the label
Resource usage
on Oct 2, 2019
DrahtBot added the label
Needs rebase
on Oct 15, 2019
achow101 force-pushed
on Oct 16, 2019
achow101 force-pushed
on Oct 21, 2019
DrahtBot removed the label
Needs rebase
on Oct 21, 2019
DrahtBot added the label
Needs rebase
on Oct 29, 2019
achow101 force-pushed
on Oct 29, 2019
DrahtBot removed the label
Needs rebase
on Oct 29, 2019
DrahtBot added the label
Needs rebase
on Nov 4, 2019
achow101 force-pushed
on Nov 4, 2019
DrahtBot removed the label
Needs rebase
on Nov 4, 2019
DrahtBot added the label
Needs rebase
on Nov 8, 2019
achow101 force-pushed
on Nov 8, 2019
DrahtBot removed the label
Needs rebase
on Nov 8, 2019
DrahtBot added the label
Needs rebase
on Nov 22, 2019
achow101 force-pushed
on Nov 22, 2019
DrahtBot removed the label
Needs rebase
on Nov 22, 2019
DrahtBot added the label
Needs rebase
on Dec 12, 2019
achow101 force-pushed
on Dec 12, 2019
DrahtBot removed the label
Needs rebase
on Dec 12, 2019
achow101 force-pushed
on Dec 12, 2019
elichai
commented at 5:43 pm on December 15, 2019:
contributor
Concept ACK.
I’m just playing with replacing a couple std::set with std::unordered_set and std::map with std::unordered_map and I also need access to a more public SaltedOutpointHasher.
DrahtBot added the label
Needs rebase
on Jan 30, 2020
achow101 force-pushed
on Jan 30, 2020
DrahtBot removed the label
Needs rebase
on Jan 30, 2020
DrahtBot added the label
Needs rebase
on Feb 3, 2020
achow101 force-pushed
on Feb 11, 2020
DrahtBot removed the label
Needs rebase
on Feb 11, 2020
DrahtBot added the label
Needs rebase
on Mar 9, 2020
achow101 force-pushed
on Mar 10, 2020
DrahtBot removed the label
Needs rebase
on Mar 10, 2020
DrahtBot added the label
Needs rebase
on Apr 22, 2020
achow101 force-pushed
on Apr 22, 2020
DrahtBot removed the label
Needs rebase
on Apr 22, 2020
DrahtBot added the label
Needs rebase
on May 4, 2020
achow101 force-pushed
on May 4, 2020
DrahtBot removed the label
Needs rebase
on May 4, 2020
DrahtBot added the label
Needs rebase
on May 6, 2020
achow101 force-pushed
on May 12, 2020
DrahtBot removed the label
Needs rebase
on May 12, 2020
hebasto
commented at 2:33 pm on June 27, 2020:
member
Concept ACK on using hashed containers.
hebasto
commented at 2:38 pm on June 27, 2020:
member
Why not using auto for iterators type? It could improve readability a bit :)
33+ SaltedOutpointHasher();
34+
35+ /**
36+ * This *must* return size_t. With Boost 1.46 on 32-bit systems the
37+ * unordered_map will behave unpredictably if the custom hasher returns a
38+ * uint64_t, resulting in failures when syncing the chain (#4634).
Oops, that’s from a previous iteration of this PR. Removed.
in
src/saltedhash.cpp:6
in
2ba96b0438outdated
0@@ -0,0 +1,10 @@
1+// Copyright (c) 2019 The Bitcoin Core developers
2+// Distributed under the MIT software license, see the accompanying
3+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+#include <random.h>
6+#include <saltedhash.h>
hebasto
commented at 9:57 am on July 2, 2020:
member
ACK4b3439ffa93e7de1ce2fefcb16e989e5a1805569, tested on Linux Mint 20 (x86_64).
Did not make benchmarks, though.
e89c19a157d504492e0665fee81cac496d5fc7f6
Why are operator() definitions not placed in the header, that could imply inlining?
achow101
commented at 2:56 pm on July 2, 2020:
member
Why are operator() definitions not placed in the header, that could imply inlining?
I’m not sure that it matters since we never call operator() directly ourselves.
Move SaltedTxidHasher and SaltedOutPointHasher to saltedhash.{cpp/h}76bd5b05dc
Change getWalletTxs to return a set instead of a vector23eb02c755
Change mapWallet to be a std::unordered_map864bc3bfda
Change mapTxSpends to be a std::unordered_multimapdec73a3188
Add SaltedHashers for CKeyID, CScriptID, CPubKey, and CScript
SaltedKeyIDHasher uses CSipHasher for hashing CKeyIDs
SaltedScriptIDHasher uses CSipHasher for hashing CScriptIDs
SaltedPubkeyasher uses CSipHasher for hashing CPubKeys
SaltedScriptHasher uses CSipHasher for hashing CScripts
11d172ca41
Use std::unordered_map and std::unordered_set in various places in the wallet
Change mapKeys, mapScripts, mapCryptedKeys, mapKeyMetadata, m_script_metadata, mapWatchKeys
to use std::unordered_map.
Change setWatchOnly to use std::unordered_set
8e3d1e73cd
achow101 force-pushed
on Jul 2, 2020
hebasto approved
hebasto
commented at 3:25 pm on July 2, 2020:
member
re-ACK8e3d1e73cdc560c42349989e9a41e71485a873c9, only suggested changes since the previous review.
achow101
commented at 4:00 pm on August 10, 2020:
member
This has been open for a while without much review. Closing for now, I’ll try to integrate some of these changes the next time I touch the relevant places (e.g. mapWallet when I get around to changing how transactions are stored).
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: 2024-12-22 06:12 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me