You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

memusage.h 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (c) 2015 The Bitcoin developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #ifndef BITCOIN_MEMUSAGE_H
  5. #define BITCOIN_MEMUSAGE_H
  6. #include <stdlib.h>
  7. #include <map>
  8. #include <set>
  9. #include <vector>
  10. #include <boost/foreach.hpp>
  11. #include <boost/unordered_set.hpp>
  12. #include <boost/unordered_map.hpp>
  13. namespace memusage
  14. {
  15. /** Compute the total memory used by allocating alloc bytes. */
  16. static size_t MallocUsage(size_t alloc);
  17. /** Dynamic memory usage for built-in types is zero. */
  18. static inline size_t DynamicUsage(const int8_t& v) { return 0; }
  19. static inline size_t DynamicUsage(const uint8_t& v) { return 0; }
  20. static inline size_t DynamicUsage(const int16_t& v) { return 0; }
  21. static inline size_t DynamicUsage(const uint16_t& v) { return 0; }
  22. static inline size_t DynamicUsage(const int32_t& v) { return 0; }
  23. static inline size_t DynamicUsage(const uint32_t& v) { return 0; }
  24. static inline size_t DynamicUsage(const int64_t& v) { return 0; }
  25. static inline size_t DynamicUsage(const uint64_t& v) { return 0; }
  26. static inline size_t DynamicUsage(const float& v) { return 0; }
  27. static inline size_t DynamicUsage(const double& v) { return 0; }
  28. template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; }
  29. template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; }
  30. template<typename X, typename Y> static inline size_t DynamicUsage(std::pair<X, Y> &p) { return 0; }
  31. /** Compute the memory used for dynamically allocated but owned data structures.
  32. * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
  33. * will compute the memory used for the vector<int>'s, but not for the ints inside.
  34. * This is for efficiency reasons, as these functions are intended to be fast. If
  35. * application data structures require more accurate inner accounting, they should
  36. * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching +
  37. * updating on modification.
  38. */
  39. template<typename X> static size_t DynamicUsage(const std::vector<X>& v);
  40. template<typename X> static size_t DynamicUsage(const std::set<X>& s);
  41. template<typename X, typename Y> static size_t DynamicUsage(const std::map<X, Y>& m);
  42. template<typename X, typename Y> static size_t DynamicUsage(const boost::unordered_set<X, Y>& s);
  43. template<typename X, typename Y, typename Z> static size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& s);
  44. template<typename X> static size_t DynamicUsage(const X& x);
  45. template<typename X> static size_t RecursiveDynamicUsage(const std::vector<X>& v);
  46. template<typename X> static size_t RecursiveDynamicUsage(const std::set<X>& v);
  47. template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::map<X, Y>& v);
  48. template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::pair<X, Y>& v);
  49. template<typename X> static size_t RecursiveDynamicUsage(const X& v);
  50. static inline size_t MallocUsage(size_t alloc)
  51. {
  52. // Measured on libc6 2.19 on Linux.
  53. if (sizeof(void*) == 8) {
  54. return ((alloc + 31) >> 4) << 4;
  55. } else if (sizeof(void*) == 4) {
  56. return ((alloc + 15) >> 3) << 3;
  57. } else {
  58. assert(0);
  59. }
  60. }
  61. // STL data structures
  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. template<typename X>
  73. static inline size_t DynamicUsage(const std::vector<X>& v)
  74. {
  75. return MallocUsage(v.capacity() * sizeof(X));
  76. }
  77. template<typename X>
  78. static inline size_t RecursiveDynamicUsage(const std::vector<X>& v)
  79. {
  80. size_t usage = DynamicUsage(v);
  81. BOOST_FOREACH(const X& x, v) {
  82. usage += RecursiveDynamicUsage(x);
  83. }
  84. return usage;
  85. }
  86. template<typename X>
  87. static inline size_t DynamicUsage(const std::set<X>& s)
  88. {
  89. return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
  90. }
  91. template<typename X>
  92. static inline size_t RecursiveDynamicUsage(const std::set<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. template<typename X, typename Y>
  101. static inline size_t DynamicUsage(const std::map<X, Y>& m)
  102. {
  103. return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size();
  104. }
  105. template<typename X, typename Y>
  106. static inline size_t RecursiveDynamicUsage(const std::map<X, Y>& v)
  107. {
  108. size_t usage = DynamicUsage(v);
  109. for (typename std::map<X, Y>::const_iterator it = v.begin(); it != v.end(); it++) {
  110. usage += RecursiveDynamicUsage(*it);
  111. }
  112. return usage;
  113. }
  114. template<typename X, typename Y>
  115. static inline size_t RecursiveDynamicUsage(const std::pair<X, Y>& v)
  116. {
  117. return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second);
  118. }
  119. // Boost data structures
  120. template<typename X>
  121. struct boost_unordered_node : private X
  122. {
  123. private:
  124. void* ptr;
  125. };
  126. template<typename X, typename Y>
  127. static inline size_t DynamicUsage(const boost::unordered_set<X, Y>& s)
  128. {
  129. return MallocUsage(sizeof(boost_unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count());
  130. }
  131. template<typename X, typename Y, typename Z>
  132. static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m)
  133. {
  134. return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
  135. }
  136. // Dispatch to class method as fallback
  137. template<typename X>
  138. static inline size_t DynamicUsage(const X& x)
  139. {
  140. return x.DynamicMemoryUsage();
  141. }
  142. template<typename X>
  143. static inline size_t RecursiveDynamicUsage(const X& x)
  144. {
  145. return DynamicUsage(x);
  146. }
  147. }
  148. #endif