Branch data Line data Source code
# 1 : : // Copyright (c) 2015-2020 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 : : #ifndef BITCOIN_MEMUSAGE_H
# 6 : : #define BITCOIN_MEMUSAGE_H
# 7 : :
# 8 : : #include <indirectmap.h>
# 9 : : #include <prevector.h>
# 10 : :
# 11 : : #include <stdlib.h>
# 12 : :
# 13 : : #include <cassert>
# 14 : : #include <map>
# 15 : : #include <memory>
# 16 : : #include <set>
# 17 : : #include <vector>
# 18 : : #include <unordered_map>
# 19 : : #include <unordered_set>
# 20 : :
# 21 : :
# 22 : : namespace memusage
# 23 : : {
# 24 : :
# 25 : : /** Compute the total memory used by allocating alloc bytes. */
# 26 : : static size_t MallocUsage(size_t alloc);
# 27 : :
# 28 : : /** Dynamic memory usage for built-in types is zero. */
# 29 : 0 : static inline size_t DynamicUsage(const int8_t& v) { return 0; }
# 30 : 0 : static inline size_t DynamicUsage(const uint8_t& v) { return 0; }
# 31 : 0 : static inline size_t DynamicUsage(const int16_t& v) { return 0; }
# 32 : 0 : static inline size_t DynamicUsage(const uint16_t& v) { return 0; }
# 33 : 0 : static inline size_t DynamicUsage(const int32_t& v) { return 0; }
# 34 : 0 : static inline size_t DynamicUsage(const uint32_t& v) { return 0; }
# 35 : 0 : static inline size_t DynamicUsage(const int64_t& v) { return 0; }
# 36 : 0 : static inline size_t DynamicUsage(const uint64_t& v) { return 0; }
# 37 : 0 : static inline size_t DynamicUsage(const float& v) { return 0; }
# 38 : 0 : static inline size_t DynamicUsage(const double& v) { return 0; }
# 39 : : template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; }
# 40 : : template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; }
# 41 : :
# 42 : : /** Compute the memory used for dynamically allocated but owned data structures.
# 43 : : * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
# 44 : : * will compute the memory used for the vector<int>'s, but not for the ints inside.
# 45 : : * This is for efficiency reasons, as these functions are intended to be fast. If
# 46 : : * application data structures require more accurate inner accounting, they should
# 47 : : * iterate themselves, or use more efficient caching + updating on modification.
# 48 : : */
# 49 : :
# 50 : : static inline size_t MallocUsage(size_t alloc)
# 51 : 44466030 : {
# 52 : : // Measured on libc6 2.19 on Linux.
# 53 [ + + ][ # # ]: 44466030 : if (alloc == 0) {
# [ + + ][ + + ]
# [ + + ][ + + ]
# 54 : 29607958 : return 0;
# 55 : 29607958 : } else if (sizeof(void*) == 8) {
# 56 : 14858072 : return ((alloc + 31) >> 4) << 4;
# 57 : 14858072 : } else if (sizeof(void*) == 4) {
# 58 : 0 : return ((alloc + 15) >> 3) << 3;
# 59 : 0 : } else {
# 60 : 0 : assert(0);
# 61 : 0 : }
# 62 : 44466030 : }
# 63 : :
# 64 : : // STL data structures
# 65 : :
# 66 : : template<typename X>
# 67 : : struct stl_tree_node
# 68 : : {
# 69 : : private:
# 70 : : int color;
# 71 : : void* parent;
# 72 : : void* left;
# 73 : : void* right;
# 74 : : X x;
# 75 : : };
# 76 : :
# 77 : : struct stl_shared_counter
# 78 : : {
# 79 : : /* Various platforms use different sized counters here.
# 80 : : * Conservatively assume that they won't be larger than size_t. */
# 81 : : void* class_type;
# 82 : : size_t use_count;
# 83 : : size_t weak_count;
# 84 : : };
# 85 : :
# 86 : : template<typename X>
# 87 : : static inline size_t DynamicUsage(const std::vector<X>& v)
# 88 : 1577360 : {
# 89 : 1577360 : return MallocUsage(v.capacity() * sizeof(X));
# 90 : 1577360 : }
# 91 : :
# 92 : : template<unsigned int N, typename X, typename S, typename D>
# 93 : : static inline size_t DynamicUsage(const prevector<N, X, S, D>& v)
# 94 : 30162774 : {
# 95 : 30162774 : return MallocUsage(v.allocated_memory());
# 96 : 30162774 : }
# 97 : :
# 98 : : template<typename X, typename Y>
# 99 : : static inline size_t DynamicUsage(const std::set<X, Y>& s)
# 100 : 10589528 : {
# 101 : 10589528 : return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
# 102 : 10589528 : }
# 103 : :
# 104 : : template<typename X, typename Y>
# 105 : : static inline size_t IncrementalDynamicUsage(const std::set<X, Y>& s)
# 106 : 26554 : {
# 107 : 26554 : return MallocUsage(sizeof(stl_tree_node<X>));
# 108 : 26554 : }
# 109 : :
# 110 : : template<typename X, typename Y, typename Z>
# 111 : : static inline size_t DynamicUsage(const std::map<X, Y, Z>& m)
# 112 : 267583 : {
# 113 : 267583 : return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size();
# 114 : 267583 : }
# 115 : :
# 116 : : template<typename X, typename Y, typename Z>
# 117 : : static inline size_t IncrementalDynamicUsage(const std::map<X, Y, Z>& m)
# 118 : : {
# 119 : : return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >));
# 120 : : }
# 121 : :
# 122 : : // indirectmap has underlying map with pointer as key
# 123 : :
# 124 : : template<typename X, typename Y>
# 125 : : static inline size_t DynamicUsage(const indirectmap<X, Y>& m)
# 126 : 267583 : {
# 127 : 267583 : return MallocUsage(sizeof(stl_tree_node<std::pair<const X*, Y> >)) * m.size();
# 128 : 267583 : }
# 129 : :
# 130 : : template<typename X, typename Y>
# 131 : : static inline size_t IncrementalDynamicUsage(const indirectmap<X, Y>& m)
# 132 : : {
# 133 : : return MallocUsage(sizeof(stl_tree_node<std::pair<const X*, Y> >));
# 134 : : }
# 135 : :
# 136 : : template<typename X>
# 137 : : static inline size_t DynamicUsage(const std::unique_ptr<X>& p)
# 138 : : {
# 139 : : return p ? MallocUsage(sizeof(X)) : 0;
# 140 : : }
# 141 : :
# 142 : : template<typename X>
# 143 : : static inline size_t DynamicUsage(const std::shared_ptr<X>& p)
# 144 : 96946 : {
# 145 : : // A shared_ptr can either use a single continuous memory block for both
# 146 : : // the counter and the storage (when using std::make_shared), or separate.
# 147 : : // We can't observe the difference, however, so assume the worst.
# 148 [ + - ][ + - ]: 96946 : return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0;
# 149 : 96946 : }
# 150 : :
# 151 : : template<typename X>
# 152 : : struct unordered_node : private X
# 153 : : {
# 154 : : private:
# 155 : : void* ptr;
# 156 : : };
# 157 : :
# 158 : : template<typename X, typename Y>
# 159 : : static inline size_t DynamicUsage(const std::unordered_set<X, Y>& s)
# 160 : : {
# 161 : : return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count());
# 162 : : }
# 163 : :
# 164 : : template<typename X, typename Y, typename Z>
# 165 : : static inline size_t DynamicUsage(const std::unordered_map<X, Y, Z>& m)
# 166 : 552626 : {
# 167 : 552626 : return MallocUsage(sizeof(unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
# 168 : 552626 : }
# 169 : :
# 170 : : }
# 171 : :
# 172 : : #endif // BITCOIN_MEMUSAGE_H
|