Bitcoin ABC 0.30.5
P2P Digital Currency
memusage.h
Go to the documentation of this file.
1// Copyright (c) 2015-2016 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>
11
12#include <cassert>
13#include <cstdlib>
14#include <map>
15#include <memory>
16#include <set>
17#include <unordered_map>
18#include <unordered_set>
19#include <vector>
20
21namespace memusage {
22
24static size_t MallocUsage(size_t alloc);
25
27static inline size_t DynamicUsage(const int8_t &v) {
28 return 0;
29}
30static inline size_t DynamicUsage(const uint8_t &v) {
31 return 0;
32}
33static inline size_t DynamicUsage(const int16_t &v) {
34 return 0;
35}
36static inline size_t DynamicUsage(const uint16_t &v) {
37 return 0;
38}
39static inline size_t DynamicUsage(const int32_t &v) {
40 return 0;
41}
42static inline size_t DynamicUsage(const uint32_t &v) {
43 return 0;
44}
45static inline size_t DynamicUsage(const int64_t &v) {
46 return 0;
47}
48static inline size_t DynamicUsage(const uint64_t &v) {
49 return 0;
50}
51static inline size_t DynamicUsage(const float &v) {
52 return 0;
53}
54static inline size_t DynamicUsage(const double &v) {
55 return 0;
56}
57template <typename X> static inline size_t DynamicUsage(X *const &v) {
58 return 0;
59}
60template <typename X> static inline size_t DynamicUsage(const X *const &v) {
61 return 0;
62}
63
73static inline size_t MallocUsage(size_t alloc) {
74 // Measured on libc6 2.19 on Linux.
75 if (alloc == 0) {
76 return 0;
77 } else if (sizeof(void *) == 8) {
78 return ((alloc + 31) >> 4) << 4;
79 } else if (sizeof(void *) == 4) {
80 return ((alloc + 15) >> 3) << 3;
81 } else {
82 assert(0);
83 }
84}
85
86// STL data structures
87
88template <typename X> struct stl_tree_node {
89private:
90 int color;
91 void *parent;
92 void *left;
93 void *right;
94 X x;
95};
96
103 size_t use_count;
105};
106
107template <typename X>
108static inline size_t DynamicUsage(const std::vector<X> &v) {
109 return MallocUsage(v.capacity() * sizeof(X));
110}
111
112template <unsigned int N, typename X, typename S, typename D>
113static inline size_t DynamicUsage(const prevector<N, X, S, D> &v) {
114 return MallocUsage(v.allocated_memory());
115}
116
117template <typename X, typename Y>
118static inline size_t DynamicUsage(const std::set<X, Y> &s) {
119 return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
120}
121
122template <typename X, typename Y>
123static inline size_t IncrementalDynamicUsage(const std::set<X, Y> &s) {
124 return MallocUsage(sizeof(stl_tree_node<X>));
125}
126
127template <typename X, typename Y, typename Z>
128static inline size_t DynamicUsage(const std::map<X, Y, Z> &m) {
129 return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y>>)) * m.size();
130}
131
132template <typename X, typename Y, typename Z>
133static inline size_t IncrementalDynamicUsage(const std::map<X, Y, Z> &m) {
134 return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y>>));
135}
136
137// indirectmap has underlying map with pointer as key
138
139template <typename X, typename Y>
140static inline size_t DynamicUsage(const indirectmap<X, Y> &m) {
141 return MallocUsage(sizeof(stl_tree_node<std::pair<const X *, Y>>)) *
142 m.size();
143}
144
145template <typename X, typename Y>
146static inline size_t IncrementalDynamicUsage(const indirectmap<X, Y> &m) {
147 return MallocUsage(sizeof(stl_tree_node<std::pair<const X *, Y>>));
148}
149
150template <typename X>
151static inline size_t DynamicUsage(const std::unique_ptr<X> &p) {
152 return p ? MallocUsage(sizeof(X)) : 0;
153}
154
155template <typename X>
156static inline size_t DynamicUsage(const std::shared_ptr<X> &p) {
157 // A shared_ptr can either use a single continuous memory block for both the
158 // counter and the storage (when using std::make_shared), or separate. We
159 // can't observe the difference, however, so assume the worst.
160 return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter))
161 : 0;
162}
163
164// Boost data structures
165
166template <typename X> struct unordered_node : private X {
167private:
168 void *ptr;
169};
170
171template <typename X, typename Y>
172static inline size_t DynamicUsage(const std::unordered_set<X, Y> &s) {
173 return MallocUsage(sizeof(unordered_node<X>)) * s.size() +
174 MallocUsage(sizeof(void *) * s.bucket_count());
175}
176
177template <typename X, typename Y, typename Z>
178static inline size_t DynamicUsage(const std::unordered_map<X, Y, Z> &m) {
179 return MallocUsage(sizeof(unordered_node<std::pair<const X, Y>>)) *
180 m.size() +
181 MallocUsage(sizeof(void *) * m.bucket_count());
182}
183
184template <class Key, class T, class Hash, class Pred,
185 std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>
186static inline size_t DynamicUsage(
187 const std::unordered_map<Key, T, Hash, Pred,
188 PoolAllocator<std::pair<const Key, T>,
189 MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>>
190 &m) {
191 auto *pool_resource = m.get_allocator().resource();
192
193 // The allocated chunks are stored in a std::list. Size per node should
194 // therefore be 3 pointers: next, previous, and a pointer to the chunk.
195 size_t estimated_list_node_size = MallocUsage(sizeof(void *) * 3);
196 size_t usage_resource =
197 estimated_list_node_size * pool_resource->NumAllocatedChunks();
198 size_t usage_chunks = MallocUsage(pool_resource->ChunkSizeBytes()) *
199 pool_resource->NumAllocatedChunks();
200 return usage_resource + usage_chunks +
201 MallocUsage(sizeof(void *) * m.bucket_count());
202}
203
204} // namespace memusage
205
206#endif // BITCOIN_MEMUSAGE_H
Forwards all allocations/deallocations to the PoolResource.
Definition: pool.h:299
Map whose keys are pointers, but are compared by their dereferenced values.
Definition: indirectmap.h:26
size_type size() const
Definition: indirectmap.h:54
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:38
size_t allocated_memory() const
Definition: prevector.h:610
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:74
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition: memusage.h:27
static size_t IncrementalDynamicUsage(const std::set< X, Y > &s)
Definition: memusage.h:123
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
Definition: memusage.h:73
void * class_type
Various platforms use different sized counters here.
Definition: memusage.h:102
assert(!tx.IsCoinBase())