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