From 540629c6fbbfc2aed336f7c7de1b2573d3310fda Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 May 2015 00:20:46 +0200 Subject: [PATCH] Add memusage.h --- src/Makefile.am | 1 + src/memusage.h | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 src/memusage.h diff --git a/src/Makefile.am b/src/Makefile.am index 72d79619b..d85ce0f08 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,6 +100,7 @@ BITCOIN_CORE_H = \ leveldbwrapper.h \ limitedmap.h \ main.h \ + memusage.h \ merkleblock.h \ miner.h \ mruset.h \ diff --git a/src/memusage.h b/src/memusage.h new file mode 100644 index 000000000..9f7de9e2e --- /dev/null +++ b/src/memusage.h @@ -0,0 +1,111 @@ +// Copyright (c) 2015 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_MEMUSAGE_H +#define BITCOIN_MEMUSAGE_H + +#include + +#include +#include +#include + +#include +#include + +namespace memusage +{ + +/** Compute the total memory used by allocating alloc bytes. */ +static size_t MallocUsage(size_t alloc); + +/** Compute the memory used for dynamically allocated but owned data structures. + * For generic data types, this is *not* recursive. DynamicUsage(vector >) + * will compute the memory used for the vector'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 + * do the recursion themselves, or use more efficient caching + updating on modification. + */ +template static size_t DynamicUsage(const std::vector& v); +template static size_t DynamicUsage(const std::set& s); +template static size_t DynamicUsage(const std::map& m); +template static size_t DynamicUsage(const boost::unordered_set& s); +template static size_t DynamicUsage(const boost::unordered_map& s); +template static size_t DynamicUsage(const X& x); + +static inline size_t MallocUsage(size_t alloc) +{ + // Measured on libc6 2.19 on Linux. + if (sizeof(void*) == 8) { + return ((alloc + 31) >> 4) << 4; + } else if (sizeof(void*) == 4) { + return ((alloc + 15) >> 3) << 3; + } else { + assert(0); + } +} + +// STL data structures + +template +struct stl_tree_node +{ +private: + int color; + void* parent; + void* left; + void* right; + X x; +}; + +template +static inline size_t DynamicUsage(const std::vector& v) +{ + return MallocUsage(v.capacity() * sizeof(X)); +} + +template +static inline size_t DynamicUsage(const std::set& s) +{ + return MallocUsage(sizeof(stl_tree_node)) * s.size(); +} + +template +static inline size_t DynamicUsage(const std::map& m) +{ + return MallocUsage(sizeof(stl_tree_node >)) * m.size(); +} + +// Boost data structures + +template +struct boost_unordered_node : private X +{ +private: + void* ptr; +}; + +template +static inline size_t DynamicUsage(const boost::unordered_set& s) +{ + return MallocUsage(sizeof(boost_unordered_node)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count()); +} + +template +static inline size_t DynamicUsage(const boost::unordered_map& m) +{ + return MallocUsage(sizeof(boost_unordered_node >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); +} + +// Dispatch to class method as fallback + +template +static inline size_t DynamicUsage(const X& x) +{ + return x.DynamicMemoryUsage(); +} + +} + +#endif