Various performance tweaks to CCoinsView
* Pass txid's to CCoinsView functions by reference instead of by value * Add a method to swap CCoins, and use it in some places to avoid a allocating copy + destruct. * Optimize CCoinsViewCache::FetchCoins to do only a single search through the backing map.
This commit is contained in:
parent
71eccdeaff
commit
f369d02c51
4 changed files with 47 additions and 37 deletions
37
src/main.cpp
37
src/main.cpp
|
@ -171,9 +171,9 @@ void static ResendWalletTransactions()
|
||||||
// CCoinsView implementations
|
// CCoinsView implementations
|
||||||
//
|
//
|
||||||
|
|
||||||
bool CCoinsView::GetCoins(uint256 txid, CCoins &coins) { return false; }
|
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) { return false; }
|
||||||
bool CCoinsView::SetCoins(uint256 txid, const CCoins &coins) { return false; }
|
bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; }
|
||||||
bool CCoinsView::HaveCoins(uint256 txid) { return false; }
|
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; }
|
||||||
CBlockIndex *CCoinsView::GetBestBlock() { return NULL; }
|
CBlockIndex *CCoinsView::GetBestBlock() { return NULL; }
|
||||||
bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; }
|
bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; }
|
||||||
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return false; }
|
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return false; }
|
||||||
|
@ -181,9 +181,9 @@ bool CCoinsView::GetStats(CCoinsStats &stats) { return false; }
|
||||||
|
|
||||||
|
|
||||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { }
|
CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { }
|
||||||
bool CCoinsViewBacked::GetCoins(uint256 txid, CCoins &coins) { return base->GetCoins(txid, coins); }
|
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) { return base->GetCoins(txid, coins); }
|
||||||
bool CCoinsViewBacked::SetCoins(uint256 txid, const CCoins &coins) { return base->SetCoins(txid, coins); }
|
bool CCoinsViewBacked::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); }
|
||||||
bool CCoinsViewBacked::HaveCoins(uint256 txid) { return base->HaveCoins(txid); }
|
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(txid); }
|
||||||
CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
|
CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
|
||||||
bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); }
|
bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); }
|
||||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||||
|
@ -192,7 +192,7 @@ bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stat
|
||||||
|
|
||||||
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), pindexTip(NULL) { }
|
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), pindexTip(NULL) { }
|
||||||
|
|
||||||
bool CCoinsViewCache::GetCoins(uint256 txid, CCoins &coins) {
|
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
|
||||||
if (cacheCoins.count(txid)) {
|
if (cacheCoins.count(txid)) {
|
||||||
coins = cacheCoins[txid];
|
coins = cacheCoins[txid];
|
||||||
return true;
|
return true;
|
||||||
|
@ -204,29 +204,30 @@ bool CCoinsViewCache::GetCoins(uint256 txid, CCoins &coins) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint256,CCoins>::iterator CCoinsViewCache::FetchCoins(uint256 txid) {
|
std::map<uint256,CCoins>::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
|
||||||
std::map<uint256,CCoins>::iterator it = cacheCoins.find(txid);
|
std::map<uint256,CCoins>::iterator it = cacheCoins.lower_bound(txid);
|
||||||
if (it != cacheCoins.end())
|
if (it != cacheCoins.end() && it->first == txid)
|
||||||
return it;
|
return it;
|
||||||
CCoins tmp;
|
CCoins tmp;
|
||||||
if (!base->GetCoins(txid,tmp))
|
if (!base->GetCoins(txid,tmp))
|
||||||
return it;
|
return cacheCoins.end();
|
||||||
std::pair<std::map<uint256,CCoins>::iterator,bool> ret = cacheCoins.insert(std::make_pair(txid, tmp));
|
std::map<uint256,CCoins>::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins()));
|
||||||
return ret.first;
|
tmp.swap(ret->second);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCoins &CCoinsViewCache::GetCoins(uint256 txid) {
|
CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) {
|
||||||
std::map<uint256,CCoins>::iterator it = FetchCoins(txid);
|
std::map<uint256,CCoins>::iterator it = FetchCoins(txid);
|
||||||
assert(it != cacheCoins.end());
|
assert(it != cacheCoins.end());
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::SetCoins(uint256 txid, const CCoins &coins) {
|
bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) {
|
||||||
cacheCoins[txid] = coins;
|
cacheCoins[txid] = coins;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::HaveCoins(uint256 txid) {
|
bool CCoinsViewCache::HaveCoins(const uint256 &txid) {
|
||||||
return FetchCoins(txid) != cacheCoins.end();
|
return FetchCoins(txid) != cacheCoins.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +264,7 @@ unsigned int CCoinsViewCache::GetCacheSize() {
|
||||||
It does not check for spendings by memory pool transactions. */
|
It does not check for spendings by memory pool transactions. */
|
||||||
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
|
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
|
||||||
|
|
||||||
bool CCoinsViewMemPool::GetCoins(uint256 txid, CCoins &coins) {
|
bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
|
||||||
if (base->GetCoins(txid, coins))
|
if (base->GetCoins(txid, coins))
|
||||||
return true;
|
return true;
|
||||||
if (mempool.exists(txid)) {
|
if (mempool.exists(txid)) {
|
||||||
|
@ -274,7 +275,7 @@ bool CCoinsViewMemPool::GetCoins(uint256 txid, CCoins &coins) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewMemPool::HaveCoins(uint256 txid) {
|
bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
|
||||||
return mempool.exists(txid) || base->HaveCoins(txid);
|
return mempool.exists(txid) || base->HaveCoins(txid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/main.h
35
src/main.h
|
@ -918,6 +918,15 @@ public:
|
||||||
void Cleanup() {
|
void Cleanup() {
|
||||||
while (vout.size() > 0 && vout.back().IsNull())
|
while (vout.size() > 0 && vout.back().IsNull())
|
||||||
vout.pop_back();
|
vout.pop_back();
|
||||||
|
if (vout.empty())
|
||||||
|
std::vector<CTxOut>().swap(vout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(CCoins &to) {
|
||||||
|
std::swap(to.fCoinBase, fCoinBase);
|
||||||
|
to.vout.swap(vout);
|
||||||
|
std::swap(to.nHeight, nHeight);
|
||||||
|
std::swap(to.nVersion, nVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// equality test
|
// equality test
|
||||||
|
@ -2077,14 +2086,14 @@ class CCoinsView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Retrieve the CCoins (unspent transaction outputs) for a given txid
|
// Retrieve the CCoins (unspent transaction outputs) for a given txid
|
||||||
virtual bool GetCoins(uint256 txid, CCoins &coins);
|
virtual bool GetCoins(const uint256 &txid, CCoins &coins);
|
||||||
|
|
||||||
// Modify the CCoins for a given txid
|
// Modify the CCoins for a given txid
|
||||||
virtual bool SetCoins(uint256 txid, const CCoins &coins);
|
virtual bool SetCoins(const uint256 &txid, const CCoins &coins);
|
||||||
|
|
||||||
// Just check whether we have data for a given txid.
|
// Just check whether we have data for a given txid.
|
||||||
// This may (but cannot always) return true for fully spent transactions
|
// This may (but cannot always) return true for fully spent transactions
|
||||||
virtual bool HaveCoins(uint256 txid);
|
virtual bool HaveCoins(const uint256 &txid);
|
||||||
|
|
||||||
// Retrieve the block index whose state this CCoinsView currently represents
|
// Retrieve the block index whose state this CCoinsView currently represents
|
||||||
virtual CBlockIndex *GetBestBlock();
|
virtual CBlockIndex *GetBestBlock();
|
||||||
|
@ -2110,9 +2119,9 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CCoinsViewBacked(CCoinsView &viewIn);
|
CCoinsViewBacked(CCoinsView &viewIn);
|
||||||
bool GetCoins(uint256 txid, CCoins &coins);
|
bool GetCoins(const uint256 &txid, CCoins &coins);
|
||||||
bool SetCoins(uint256 txid, const CCoins &coins);
|
bool SetCoins(const uint256 &txid, const CCoins &coins);
|
||||||
bool HaveCoins(uint256 txid);
|
bool HaveCoins(const uint256 &txid);
|
||||||
CBlockIndex *GetBestBlock();
|
CBlockIndex *GetBestBlock();
|
||||||
bool SetBestBlock(CBlockIndex *pindex);
|
bool SetBestBlock(CBlockIndex *pindex);
|
||||||
void SetBackend(CCoinsView &viewIn);
|
void SetBackend(CCoinsView &viewIn);
|
||||||
|
@ -2131,9 +2140,9 @@ public:
|
||||||
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
||||||
|
|
||||||
// Standard CCoinsView methods
|
// Standard CCoinsView methods
|
||||||
bool GetCoins(uint256 txid, CCoins &coins);
|
bool GetCoins(const uint256 &txid, CCoins &coins);
|
||||||
bool SetCoins(uint256 txid, const CCoins &coins);
|
bool SetCoins(const uint256 &txid, const CCoins &coins);
|
||||||
bool HaveCoins(uint256 txid);
|
bool HaveCoins(const uint256 &txid);
|
||||||
CBlockIndex *GetBestBlock();
|
CBlockIndex *GetBestBlock();
|
||||||
bool SetBestBlock(CBlockIndex *pindex);
|
bool SetBestBlock(CBlockIndex *pindex);
|
||||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||||
|
@ -2141,7 +2150,7 @@ public:
|
||||||
// Return a modifiable reference to a CCoins. Check HaveCoins first.
|
// Return a modifiable reference to a CCoins. Check HaveCoins first.
|
||||||
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
|
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
|
||||||
// copying.
|
// copying.
|
||||||
CCoins &GetCoins(uint256 txid);
|
CCoins &GetCoins(const uint256 &txid);
|
||||||
|
|
||||||
// Push the modifications applied to this cache to its base.
|
// Push the modifications applied to this cache to its base.
|
||||||
// Failure to call this method before destruction will cause the changes to be forgotten.
|
// Failure to call this method before destruction will cause the changes to be forgotten.
|
||||||
|
@ -2151,7 +2160,7 @@ public:
|
||||||
unsigned int GetCacheSize();
|
unsigned int GetCacheSize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<uint256,CCoins>::iterator FetchCoins(uint256 txid);
|
std::map<uint256,CCoins>::iterator FetchCoins(const uint256 &txid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** CCoinsView that brings transactions from a memorypool into view.
|
/** CCoinsView that brings transactions from a memorypool into view.
|
||||||
|
@ -2163,8 +2172,8 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn);
|
CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn);
|
||||||
bool GetCoins(uint256 txid, CCoins &coins);
|
bool GetCoins(const uint256 &txid, CCoins &coins);
|
||||||
bool HaveCoins(uint256 txid);
|
bool HaveCoins(const uint256 &txid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Global variable that points to the active CCoinsView (protected by cs_main) */
|
/** Global variable that points to the active CCoinsView (protected by cs_main) */
|
||||||
|
|
|
@ -22,17 +22,17 @@ void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
|
||||||
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "coins", nCacheSize, fMemory, fWipe) {
|
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "coins", nCacheSize, fMemory, fWipe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) {
|
bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
|
||||||
return db.Read(make_pair('c', txid), coins);
|
return db.Read(make_pair('c', txid), coins);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) {
|
bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
BatchWriteCoins(batch, txid, coins);
|
BatchWriteCoins(batch, txid, coins);
|
||||||
return db.WriteBatch(batch);
|
return db.WriteBatch(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::HaveCoins(uint256 txid) {
|
bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
|
||||||
return db.Exists(make_pair('c', txid));
|
return db.Exists(make_pair('c', txid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ protected:
|
||||||
public:
|
public:
|
||||||
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
|
|
||||||
bool GetCoins(uint256 txid, CCoins &coins);
|
bool GetCoins(const uint256 &txid, CCoins &coins);
|
||||||
bool SetCoins(uint256 txid, const CCoins &coins);
|
bool SetCoins(const uint256 &txid, const CCoins &coins);
|
||||||
bool HaveCoins(uint256 txid);
|
bool HaveCoins(const uint256 &txid);
|
||||||
CBlockIndex *GetBestBlock();
|
CBlockIndex *GetBestBlock();
|
||||||
bool SetBestBlock(CBlockIndex *pindex);
|
bool SetBestBlock(CBlockIndex *pindex);
|
||||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||||
|
|
Loading…
Reference in a new issue