LCOV - code coverage report
Current view: top level - src - memusage.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 21 21 100.0 %
Date: 2020-09-26 01:30:44 Functions: 13 13 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2015-2020 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>
      10             : 
      11             : #include <stdlib.h>
      12             : 
      13             : #include <cassert>
      14             : #include <map>
      15             : #include <memory>
      16             : #include <set>
      17             : #include <vector>
      18             : #include <unordered_map>
      19             : #include <unordered_set>
      20             : 
      21             : 
      22             : namespace memusage
      23             : {
      24             : 
      25             : /** Compute the total memory used by allocating alloc bytes. */
      26             : static size_t MallocUsage(size_t alloc);
      27             : 
      28             : /** Dynamic memory usage for built-in types is zero. */
      29             : static inline size_t DynamicUsage(const int8_t& v) { return 0; }
      30             : static inline size_t DynamicUsage(const uint8_t& v) { return 0; }
      31             : static inline size_t DynamicUsage(const int16_t& v) { return 0; }
      32             : static inline size_t DynamicUsage(const uint16_t& v) { return 0; }
      33             : static inline size_t DynamicUsage(const int32_t& v) { return 0; }
      34             : static inline size_t DynamicUsage(const uint32_t& v) { return 0; }
      35             : static inline size_t DynamicUsage(const int64_t& v) { return 0; }
      36             : static inline size_t DynamicUsage(const uint64_t& v) { return 0; }
      37             : static inline size_t DynamicUsage(const float& v) { return 0; }
      38             : static inline size_t DynamicUsage(const double& v) { return 0; }
      39             : template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; }
      40             : template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; }
      41             : 
      42             : /** Compute the memory used for dynamically allocated but owned data structures.
      43             :  *  For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >)
      44             :  *  will compute the memory used for the vector<int>'s, but not for the ints inside.
      45             :  *  This is for efficiency reasons, as these functions are intended to be fast. If
      46             :  *  application data structures require more accurate inner accounting, they should
      47             :  *  iterate themselves, or use more efficient caching + updating on modification.
      48             :  */
      49             : 
      50    39461176 : static inline size_t MallocUsage(size_t alloc)
      51             : {
      52             :     // Measured on libc6 2.19 on Linux.
      53    39461176 :     if (alloc == 0) {
      54    25934825 :         return 0;
      55             :     } else if (sizeof(void*) == 8) {
      56    13526351 :         return ((alloc + 31) >> 4) << 4;
      57             :     } else if (sizeof(void*) == 4) {
      58             :         return ((alloc + 15) >> 3) << 3;
      59             :     } else {
      60             :         assert(0);
      61             :     }
      62    39461176 : }
      63             : 
      64             : // STL data structures
      65             : 
      66             : template<typename X>
      67             : struct stl_tree_node
      68             : {
      69             : private:
      70             :     int color;
      71             :     void* parent;
      72             :     void* left;
      73             :     void* right;
      74             :     X x;
      75             : };
      76             : 
      77             : struct stl_shared_counter
      78             : {
      79             :     /* Various platforms use different sized counters here.
      80             :      * Conservatively assume that they won't be larger than size_t. */
      81             :     void* class_type;
      82             :     size_t use_count;
      83             :     size_t weak_count;
      84             : };
      85             : 
      86             : template<typename X>
      87      679586 : static inline size_t DynamicUsage(const std::vector<X>& v)
      88             : {
      89      679586 :     return MallocUsage(v.capacity() * sizeof(X));
      90             : }
      91             : 
      92             : template<unsigned int N, typename X, typename S, typename D>
      93    26806225 : static inline size_t DynamicUsage(const prevector<N, X, S, D>& v)
      94             : {
      95    26806225 :     return MallocUsage(v.allocated_memory());
      96             : }
      97             : 
      98             : template<typename X, typename Y>
      99    10331164 : static inline size_t DynamicUsage(const std::set<X, Y>& s)
     100             : {
     101    10331164 :     return MallocUsage(sizeof(stl_tree_node<X>)) * s.size();
     102             : }
     103             : 
     104             : template<typename X, typename Y>
     105      161236 : static inline size_t IncrementalDynamicUsage(const std::set<X, Y>& s)
     106             : {
     107      161236 :     return MallocUsage(sizeof(stl_tree_node<X>));
     108             : }
     109             : 
     110             : template<typename X, typename Y, typename Z>
     111      194583 : static inline size_t DynamicUsage(const std::map<X, Y, Z>& m)
     112             : {
     113      194583 :     return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size();
     114             : }
     115             : 
     116             : template<typename X, typename Y, typename Z>
     117             : static inline size_t IncrementalDynamicUsage(const std::map<X, Y, Z>& m)
     118             : {
     119             :     return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >));
     120             : }
     121             : 
     122             : // indirectmap has underlying map with pointer as key
     123             : 
     124             : template<typename X, typename Y>
     125      194583 : static inline size_t DynamicUsage(const indirectmap<X, Y>& m)
     126             : {
     127      194583 :     return MallocUsage(sizeof(stl_tree_node<std::pair<const X*, Y> >)) * m.size();
     128             : }
     129             : 
     130             : template<typename X, typename Y>
     131             : static inline size_t IncrementalDynamicUsage(const indirectmap<X, Y>& m)
     132             : {
     133             :     return MallocUsage(sizeof(stl_tree_node<std::pair<const X*, Y> >));
     134             : }
     135             : 
     136             : template<typename X>
     137             : static inline size_t DynamicUsage(const std::unique_ptr<X>& p)
     138             : {
     139             :     return p ? MallocUsage(sizeof(X)) : 0;
     140             : }
     141             : 
     142             : template<typename X>
     143       69329 : static inline size_t DynamicUsage(const std::shared_ptr<X>& p)
     144             : {
     145             :     // A shared_ptr can either use a single continuous memory block for both
     146             :     // the counter and the storage (when using std::make_shared), or separate.
     147             :     // We can't observe the difference, however, so assume the worst.
     148       69329 :     return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0;
     149             : }
     150             : 
     151             : template<typename X>
     152             : struct unordered_node : private X
     153             : {
     154             : private:
     155             :     void* ptr;
     156             : };
     157             : 
     158             : template<typename X, typename Y>
     159             : static inline size_t DynamicUsage(const std::unordered_set<X, Y>& s)
     160             : {
     161             :     return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count());
     162             : }
     163             : 
     164             : template<typename X, typename Y, typename Z>
     165      377108 : static inline size_t DynamicUsage(const std::unordered_map<X, Y, Z>& m)
     166             : {
     167      377108 :     return MallocUsage(sizeof(unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
     168             : }
     169             : 
     170             : }
     171             : 
     172             : #endif // BITCOIN_MEMUSAGE_H

Generated by: LCOV version 1.15