diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/coins.cpp | 14 | ||||
-rw-r--r-- | src/coins.h | 4 | ||||
-rw-r--r-- | src/core_memusage.h | 62 | ||||
-rw-r--r-- | src/memusage.h | 66 | ||||
-rw-r--r-- | src/primitives/transaction.cpp | 5 | ||||
-rw-r--r-- | src/primitives/transaction.h | 9 | ||||
-rw-r--r-- | src/script/script.cpp | 5 | ||||
-rw-r--r-- | src/script/script.h | 3 | ||||
-rw-r--r-- | src/test/coins_tests.cpp | 4 | ||||
-rw-r--r-- | src/txmempool.cpp | 2 |
11 files changed, 76 insertions, 99 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b82c6dc37a..cc8dded413 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ BITCOIN_CORE_H = \ consensus/params.h \ consensus/validation.h \ core_io.h \ + core_memusage.h \ eccryptoverify.h \ ecwrapper.h \ hash.h \ diff --git a/src/coins.cpp b/src/coins.cpp index a41d5a310d..f02949de53 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -83,7 +83,7 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const // version as fresh. ret->second.flags = CCoinsCacheEntry::FRESH; } - cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins); + cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage(); return ret; } @@ -110,7 +110,7 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) { ret.first->second.flags = CCoinsCacheEntry::FRESH; } } else { - cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins); + cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage(); } // Assume that whenever ModifyCoins is called, the entry will be modified. ret.first->second.flags |= CCoinsCacheEntry::DIRTY; @@ -159,7 +159,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn assert(it->second.flags & CCoinsCacheEntry::FRESH); CCoinsCacheEntry& entry = cacheCoins[it->first]; entry.coins.swap(it->second.coins); - cachedCoinsUsage += memusage::DynamicUsage(entry.coins); + cachedCoinsUsage += entry.coins.DynamicMemoryUsage(); entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH; } } else { @@ -167,13 +167,13 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn // The grandparent does not have an entry, and the child is // modified and being pruned. This means we can just delete // it from the parent. - cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage(); cacheCoins.erase(itUs); } else { // A normal modification. - cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage(); itUs->second.coins.swap(it->second.coins); - cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage(); itUs->second.flags |= CCoinsCacheEntry::DIRTY; } } @@ -261,6 +261,6 @@ CCoinsModifier::~CCoinsModifier() cache.cacheCoins.erase(it); } else { // If the coin still exists after the modification, add the new usage - cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins); + cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage(); } } diff --git a/src/coins.h b/src/coins.h index a4671645df..bf4a777b8a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -7,6 +7,7 @@ #define BITCOIN_COINS_H #include "compressor.h" +#include "core_memusage.h" #include "memusage.h" #include "serialize.h" #include "uint256.h" @@ -257,8 +258,7 @@ public: size_t DynamicMemoryUsage() const { size_t ret = memusage::DynamicUsage(vout); BOOST_FOREACH(const CTxOut &out, vout) { - const std::vector<unsigned char> *script = &out.scriptPubKey; - ret += memusage::DynamicUsage(*script); + ret += RecursiveDynamicUsage(out.scriptPubKey); } return ret; } diff --git a/src/core_memusage.h b/src/core_memusage.h new file mode 100644 index 0000000000..711135bb44 --- /dev/null +++ b/src/core_memusage.h @@ -0,0 +1,62 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CORE_MEMUSAGE_H +#define BITCOIN_CORE_MEMUSAGE_H + +#include "primitives/transaction.h" +#include "primitives/block.h" +#include "memusage.h" + +static inline size_t RecursiveDynamicUsage(const CScript& script) { + return memusage::DynamicUsage(*static_cast<const std::vector<unsigned char>*>(&script)); +} + +static inline size_t RecursiveDynamicUsage(const COutPoint& out) { + return 0; +} + +static inline size_t RecursiveDynamicUsage(const CTxIn& in) { + return RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout); +} + +static inline size_t RecursiveDynamicUsage(const CTxOut& out) { + return RecursiveDynamicUsage(out.scriptPubKey); +} + +static inline size_t RecursiveDynamicUsage(const CTransaction& tx) { + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) { + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CBlock& block) { + size_t mem = memusage::DynamicUsage(block.vtx) + memusage::DynamicUsage(block.vMerkleTree); + for (std::vector<CTransaction>::const_iterator it = block.vtx.begin(); it != block.vtx.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CBlockLocator& locator) { + return memusage::DynamicUsage(locator.vHave); +} + +#endif // BITCOIN_CORE_MEMUSAGE_H diff --git a/src/memusage.h b/src/memusage.h index 7a831e6d33..be3964df1b 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -34,28 +34,14 @@ static inline size_t DynamicUsage(const float& v) { return 0; } static inline size_t DynamicUsage(const double& v) { return 0; } template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; } template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; } -template<typename X, typename Y> static inline size_t DynamicUsage(std::pair<X, Y> &p) { return 0; } /** Compute the memory used for dynamically allocated but owned data structures. * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >) * will compute the memory used for the vector<int>'s, but not for the ints inside. * This is for efficiency reasons, as these functions are intended to be fast. If * application data structures require more accurate inner accounting, they should - * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching + - * updating on modification. + * iterate themselves, or use more efficient caching + updating on modification. */ -template<typename X> static size_t DynamicUsage(const std::vector<X>& v); -template<typename X> static size_t DynamicUsage(const std::set<X>& s); -template<typename X, typename Y> static size_t DynamicUsage(const std::map<X, Y>& m); -template<typename X, typename Y> static size_t DynamicUsage(const boost::unordered_set<X, Y>& s); -template<typename X, typename Y, typename Z> static size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& s); -template<typename X> static size_t DynamicUsage(const X& x); - -template<typename X> static size_t RecursiveDynamicUsage(const std::vector<X>& v); -template<typename X> static size_t RecursiveDynamicUsage(const std::set<X>& v); -template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::map<X, Y>& v); -template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::pair<X, Y>& v); -template<typename X> static size_t RecursiveDynamicUsage(const X& v); static inline size_t MallocUsage(size_t alloc) { @@ -89,53 +75,17 @@ static inline size_t DynamicUsage(const std::vector<X>& v) } template<typename X> -static inline size_t RecursiveDynamicUsage(const std::vector<X>& v) -{ - size_t usage = DynamicUsage(v); - BOOST_FOREACH(const X& x, v) { - usage += RecursiveDynamicUsage(x); - } - return usage; -} - -template<typename X> static inline size_t DynamicUsage(const std::set<X>& s) { return MallocUsage(sizeof(stl_tree_node<X>)) * s.size(); } -template<typename X> -static inline size_t RecursiveDynamicUsage(const std::set<X>& v) -{ - size_t usage = DynamicUsage(v); - BOOST_FOREACH(const X& x, v) { - usage += RecursiveDynamicUsage(x); - } - return usage; -} - template<typename X, typename Y> static inline size_t DynamicUsage(const std::map<X, Y>& m) { return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size(); } -template<typename X, typename Y> -static inline size_t RecursiveDynamicUsage(const std::map<X, Y>& v) -{ - size_t usage = DynamicUsage(v); - for (typename std::map<X, Y>::const_iterator it = v.begin(); it != v.end(); it++) { - usage += RecursiveDynamicUsage(*it); - } - return usage; -} - -template<typename X, typename Y> -static inline size_t RecursiveDynamicUsage(const std::pair<X, Y>& v) -{ - return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second); -} - // Boost data structures template<typename X> @@ -157,20 +107,6 @@ static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m) return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); } -// Dispatch to class method as fallback - -template<typename X> -static inline size_t DynamicUsage(const X& x) -{ - return x.DynamicMemoryUsage(); -} - -template<typename X> -static inline size_t RecursiveDynamicUsage(const X& x) -{ - return DynamicUsage(x); -} - } #endif diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 7ed2d45973..606dbea798 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -72,11 +72,6 @@ void CTransaction::UpdateHash() const *const_cast<uint256*>(&hash) = SerializeHash(*this); } -size_t CTransaction::DynamicMemoryUsage() const -{ - return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout); -} - CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 77326c64b0..6cfd93a9a1 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,7 +7,6 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" -#include "memusage.h" #include "script/script.h" #include "serialize.h" #include "uint256.h" @@ -49,8 +48,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return 0; } }; /** An input of a transaction. It contains the location of the previous @@ -99,8 +96,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); } }; /** An output of a transaction. It contains the public key that the next input @@ -171,8 +166,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); } }; struct CMutableTransaction; @@ -256,8 +249,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const; }; /** A mutable version of CTransaction. */ diff --git a/src/script/script.cpp b/src/script/script.cpp index b1d2ceeb9f..fd33924732 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -260,8 +260,3 @@ std::string CScript::ToString() const } return str; } - -size_t CScript::DynamicMemoryUsage() const -{ - return memusage::DynamicUsage(*(static_cast<const std::vector<unsigned char>*>(this))); -} diff --git a/src/script/script.h b/src/script/script.h index aea34d05f4..e39ca57f4f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H -#include "memusage.h" #include "crypto/common.h" #include <assert.h> @@ -608,8 +607,6 @@ public: // The default std::vector::clear() does not release memory. std::vector<unsigned char>().swap(*this); } - - size_t DynamicMemoryUsage() const; }; class CReserveScript diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 34b311b804..13d848311a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -70,9 +70,9 @@ public: // Manually recompute the dynamic usage of the whole data, and compare it. size_t ret = memusage::DynamicUsage(cacheCoins); for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { - ret += memusage::DynamicUsage(it->second.coins); + ret += it->second.coins.DynamicMemoryUsage(); } - BOOST_CHECK_EQUAL(memusage::DynamicUsage(*this), ret); + BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret); } }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 4caa5fc821..5bc06e5056 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -31,7 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, { nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); nModSize = tx.CalculateModifiedSize(nTxSize); - nUsageSize = tx.DynamicMemoryUsage(); + nUsageSize = RecursiveDynamicUsage(tx); } CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) |