1111#include < set>
1212#include < vector>
1313
14+ #include < boost/foreach.hpp>
1415#include < boost/unordered_set.hpp>
1516#include < boost/unordered_map.hpp>
1617
@@ -20,12 +21,28 @@ namespace memusage
2021/* * Compute the total memory used by allocating alloc bytes. */
2122static size_t MallocUsage (size_t alloc);
2223
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 ; }
37+ template <typename X, typename Y> static inline size_t DynamicUsage (std::pair<X, Y> &p) { return 0 ; }
38+
2339/* * Compute the memory used for dynamically allocated but owned data structures.
2440 * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
2541 * will compute the memory used for the vector<int>'s, but not for the ints inside.
2642 * This is for efficiency reasons, as these functions are intended to be fast. If
2743 * application data structures require more accurate inner accounting, they should
28- * do the recursion themselves, or use more efficient caching + updating on modification.
44+ * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching +
45+ * updating on modification.
2946 */
3047template <typename X> static size_t DynamicUsage (const std::vector<X>& v);
3148template <typename X> static size_t DynamicUsage (const std::set<X>& s);
@@ -34,6 +51,12 @@ template<typename X, typename Y> static size_t DynamicUsage(const boost::unorder
3451template <typename X, typename Y, typename Z> static size_t DynamicUsage (const boost::unordered_map<X, Y, Z>& s);
3552template <typename X> static size_t DynamicUsage (const X& x);
3653
54+ template <typename X> static size_t RecursiveDynamicUsage (const std::vector<X>& v);
55+ template <typename X> static size_t RecursiveDynamicUsage (const std::set<X>& v);
56+ template <typename X, typename Y> static size_t RecursiveDynamicUsage (const std::map<X, Y>& v);
57+ template <typename X, typename Y> static size_t RecursiveDynamicUsage (const std::pair<X, Y>& v);
58+ template <typename X> static size_t RecursiveDynamicUsage (const X& v);
59+
3760static inline size_t MallocUsage (size_t alloc)
3861{
3962 // Measured on libc6 2.19 on Linux.
@@ -65,18 +88,54 @@ static inline size_t DynamicUsage(const std::vector<X>& v)
6588 return MallocUsage (v.capacity () * sizeof (X));
6689}
6790
91+ template <typename X>
92+ static inline size_t RecursiveDynamicUsage (const std::vector<X>& v)
93+ {
94+ size_t usage = DynamicUsage (v);
95+ BOOST_FOREACH (const X& x, v) {
96+ usage += RecursiveDynamicUsage (x);
97+ }
98+ return usage;
99+ }
100+
68101template <typename X>
69102static inline size_t DynamicUsage (const std::set<X>& s)
70103{
71104 return MallocUsage (sizeof (stl_tree_node<X>)) * s.size ();
72105}
73106
107+ template <typename X>
108+ static inline size_t RecursiveDynamicUsage (const std::set<X>& v)
109+ {
110+ size_t usage = DynamicUsage (v);
111+ BOOST_FOREACH (const X& x, v) {
112+ usage += RecursiveDynamicUsage (x);
113+ }
114+ return usage;
115+ }
116+
74117template <typename X, typename Y>
75118static inline size_t DynamicUsage (const std::map<X, Y>& m)
76119{
77120 return MallocUsage (sizeof (stl_tree_node<std::pair<const X, Y> >)) * m.size ();
78121}
79122
123+ template <typename X, typename Y>
124+ static inline size_t RecursiveDynamicUsage (const std::map<X, Y>& v)
125+ {
126+ size_t usage = DynamicUsage (v);
127+ for (typename std::map<X, Y>::const_iterator it = v.begin (); it != v.end (); it++) {
128+ usage += RecursiveDynamicUsage (*it);
129+ }
130+ return usage;
131+ }
132+
133+ template <typename X, typename Y>
134+ static inline size_t RecursiveDynamicUsage (const std::pair<X, Y>& v)
135+ {
136+ return RecursiveDynamicUsage (v.first ) + RecursiveDynamicUsage (v.second );
137+ }
138+
80139// Boost data structures
81140
82141template <typename X>
@@ -106,6 +165,12 @@ static inline size_t DynamicUsage(const X& x)
106165 return x.DynamicMemoryUsage ();
107166}
108167
168+ template <typename X>
169+ static inline size_t RecursiveDynamicUsage (const X& x)
170+ {
171+ return DynamicUsage (x);
172+ }
173+
109174}
110175
111176#endif
0 commit comments