]>
Commit | Line | Data |
---|---|---|
540629c6 PW |
1 | // Copyright (c) 2015 The Bitcoin developers |
2 | // Distributed under the MIT software license, see the accompanying | |
bc909a7a | 3 | // file COPYING or https://www.opensource.org/licenses/mit-license.php . |
540629c6 PW |
4 | |
5 | #ifndef BITCOIN_MEMUSAGE_H | |
6 | #define BITCOIN_MEMUSAGE_H | |
7 | ||
8 | #include <stdlib.h> | |
9 | ||
10 | #include <map> | |
11 | #include <set> | |
12 | #include <vector> | |
13 | ||
bde5c8b0 | 14 | #include <boost/foreach.hpp> |
540629c6 PW |
15 | #include <boost/unordered_set.hpp> |
16 | #include <boost/unordered_map.hpp> | |
17 | ||
18 | namespace memusage | |
19 | { | |
20 | ||
21 | /** Compute the total memory used by allocating alloc bytes. */ | |
22 | static size_t MallocUsage(size_t alloc); | |
23 | ||
bde5c8b0 PW |
24 | /** Dynamic memory usage for built-in types is zero. */ |
25 | static inline size_t DynamicUsage(const int8_t& v) { return 0; } | |
26 | static inline size_t DynamicUsage(const uint8_t& v) { return 0; } | |
27 | static inline size_t DynamicUsage(const int16_t& v) { return 0; } | |
28 | static inline size_t DynamicUsage(const uint16_t& v) { return 0; } | |
29 | static inline size_t DynamicUsage(const int32_t& v) { return 0; } | |
30 | static inline size_t DynamicUsage(const uint32_t& v) { return 0; } | |
31 | static inline size_t DynamicUsage(const int64_t& v) { return 0; } | |
32 | static inline size_t DynamicUsage(const uint64_t& v) { return 0; } | |
33 | static inline size_t DynamicUsage(const float& v) { return 0; } | |
34 | static inline size_t DynamicUsage(const double& v) { return 0; } | |
35 | template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; } | |
36 | template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; } | |
bde5c8b0 | 37 | |
540629c6 PW |
38 | /** Compute the memory used for dynamically allocated but owned data structures. |
39 | * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >) | |
40 | * will compute the memory used for the vector<int>'s, but not for the ints inside. | |
41 | * This is for efficiency reasons, as these functions are intended to be fast. If | |
42 | * application data structures require more accurate inner accounting, they should | |
6bd1d60c | 43 | * iterate themselves, or use more efficient caching + updating on modification. |
540629c6 | 44 | */ |
bde5c8b0 | 45 | |
540629c6 PW |
46 | static inline size_t MallocUsage(size_t alloc) |
47 | { | |
48 | // Measured on libc6 2.19 on Linux. | |
29a8ade7 PW |
49 | if (alloc == 0) { |
50 | return 0; | |
51 | } else if (sizeof(void*) == 8) { | |
540629c6 PW |
52 | return ((alloc + 31) >> 4) << 4; |
53 | } else if (sizeof(void*) == 4) { | |
54 | return ((alloc + 15) >> 3) << 3; | |
55 | } else { | |
56 | assert(0); | |
57 | } | |
58 | } | |
59 | ||
60 | // STL data structures | |
61 | ||
62 | template<typename X> | |
63 | struct stl_tree_node | |
64 | { | |
65 | private: | |
66 | int color; | |
67 | void* parent; | |
68 | void* left; | |
69 | void* right; | |
70 | X x; | |
71 | }; | |
72 | ||
73 | template<typename X> | |
74 | static inline size_t DynamicUsage(const std::vector<X>& v) | |
75 | { | |
76 | return MallocUsage(v.capacity() * sizeof(X)); | |
77 | } | |
78 | ||
29a8ade7 PW |
79 | template<unsigned int N, typename X, typename S, typename D> |
80 | static inline size_t DynamicUsage(const prevector<N, X, S, D>& v) | |
81 | { | |
82 | return MallocUsage(v.allocated_memory()); | |
83 | } | |
84 | ||
540629c6 PW |
85 | template<typename X> |
86 | static inline size_t DynamicUsage(const std::set<X>& s) | |
87 | { | |
88 | return MallocUsage(sizeof(stl_tree_node<X>)) * s.size(); | |
89 | } | |
90 | ||
91 | template<typename X, typename Y> | |
92 | static inline size_t DynamicUsage(const std::map<X, Y>& m) | |
93 | { | |
94 | return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size(); | |
95 | } | |
96 | ||
97 | // Boost data structures | |
98 | ||
99 | template<typename X> | |
100 | struct boost_unordered_node : private X | |
101 | { | |
102 | private: | |
103 | void* ptr; | |
104 | }; | |
105 | ||
106 | template<typename X, typename Y> | |
107 | static inline size_t DynamicUsage(const boost::unordered_set<X, Y>& s) | |
108 | { | |
109 | return MallocUsage(sizeof(boost_unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count()); | |
110 | } | |
111 | ||
112 | template<typename X, typename Y, typename Z> | |
113 | static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m) | |
114 | { | |
115 | return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); | |
116 | } | |
117 | ||
540629c6 PW |
118 | } |
119 | ||
120 | #endif |