Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate core memory usage computation in core_memusage.h #6453

Merged
merged 1 commit into from Jul 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Makefile.am
Expand Up @@ -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 \
Expand Down
14 changes: 7 additions & 7 deletions src/coins.cpp
Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -159,21 +159,21 @@ 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 {
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
// 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;
}
}
Expand Down Expand Up @@ -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();
}
}
4 changes: 2 additions & 2 deletions src/coins.h
Expand Up @@ -7,6 +7,7 @@
#define BITCOIN_COINS_H

#include "compressor.h"
#include "core_memusage.h"
#include "memusage.h"
#include "serialize.h"
#include "uint256.h"
Expand Down Expand Up @@ -257,8 +258,7 @@ class CCoins
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;
}
Expand Down
62 changes: 62 additions & 0 deletions 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
66 changes: 1 addition & 65 deletions src/memusage.h
Expand Up @@ -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)
{
Expand Down Expand Up @@ -88,54 +74,18 @@ static inline size_t DynamicUsage(const std::vector<X>& v)
return MallocUsage(v.capacity() * sizeof(X));
}

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>
Expand All @@ -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
5 changes: 0 additions & 5 deletions src/primitives/transaction.cpp
Expand Up @@ -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) {
Expand Down
9 changes: 0 additions & 9 deletions src/primitives/transaction.h
Expand Up @@ -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"
Expand Down Expand Up @@ -49,8 +48,6 @@ class COutPoint
}

std::string ToString() const;

size_t DynamicMemoryUsage() const { return 0; }
};

/** An input of a transaction. It contains the location of the previous
Expand Down Expand Up @@ -99,8 +96,6 @@ class CTxIn
}

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
Expand Down Expand Up @@ -171,8 +166,6 @@ class CTxOut
}

std::string ToString() const;

size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); }
};

struct CMutableTransaction;
Expand Down Expand Up @@ -256,8 +249,6 @@ class CTransaction
}

std::string ToString() const;

size_t DynamicMemoryUsage() const;
};

/** A mutable version of CTransaction. */
Expand Down
5 changes: 0 additions & 5 deletions src/script/script.cpp
Expand Up @@ -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)));
}
3 changes: 0 additions & 3 deletions src/script/script.h
Expand Up @@ -6,7 +6,6 @@
#ifndef BITCOIN_SCRIPT_SCRIPT_H
#define BITCOIN_SCRIPT_SCRIPT_H

#include "memusage.h"
#include "crypto/common.h"

#include <assert.h>
Expand Down Expand Up @@ -608,8 +607,6 @@ class CScript : public std::vector<unsigned char>
// The default std::vector::clear() does not release memory.
std::vector<unsigned char>().swap(*this);
}

size_t DynamicMemoryUsage() const;
};

class CReserveScript
Expand Down
4 changes: 2 additions & 2 deletions src/test/coins_tests.cpp
Expand Up @@ -70,9 +70,9 @@ class CCoinsViewCacheTest : public CCoinsViewCache
// 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);
}

};
Expand Down
2 changes: 1 addition & 1 deletion src/txmempool.cpp
Expand Up @@ -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)
Expand Down