Skip to content

Commit

Permalink
improve MallocUsage() accuracy
Browse files Browse the repository at this point in the history
Co-authored-by: Pieter Wuille <[email protected]>
Co-authored-by: Martin Leitner-Ankerl <[email protected]>
  • Loading branch information
3 people committed Mar 22, 2024
1 parent 9057598 commit c6cba06
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
38 changes: 26 additions & 12 deletions src/memusage.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,28 @@ template<typename X> static inline size_t DynamicUsage(const X * const &v) { ret
* application data structures require more accurate inner accounting, they should
* iterate themselves, or use more efficient caching + updating on modification.
*/

static inline size_t MallocUsage(size_t alloc)
{
// Measured on libc6 2.19 on Linux.
if (alloc == 0) {
return 0;
} else if (sizeof(void*) == 8) {
return ((alloc + 31) >> 4) << 4;
} else if (sizeof(void*) == 4) {
return ((alloc + 15) >> 3) << 3;
} else {
assert(0);
}
// There are few if any actual zero-length allocations; when
// DynamicUsage(std::vector<X>& v) calls this function, and v.capacity() == 0,
// for example, there has not been a zero-byte allocation (which would require
// some physical space). std::vector has optimized this case. Experimental
// evidence indicates the same is true of other data structures -- there are
// no actual zero-length allocations observed, although of course this is
// library-dependent.
if (alloc == 0) return 0;

static constexpr size_t overhead = sizeof(void*);
#if defined(__arm__)
// tested with ARM 32bit
static constexpr size_t step = sizeof(void*) * 2;
static constexpr size_t min_alloc = 9;
#else
static constexpr size_t step = 16U;
static constexpr size_t min_alloc = sizeof(void*) == 8 ? 9 : 0;
#endif
// tested with Linux glibc 2.31 and 2.38, 32bit and 64bit
return (std::max(min_alloc, alloc) + overhead + (step - 1)) & ~(step - 1);
}

// STL data structures
Expand Down Expand Up @@ -164,11 +173,16 @@ static inline size_t DynamicUsage(const std::list<X>& l)
return MallocUsage(sizeof(list_node<X>)) * l.size();
}

// struct unordered_node adds the container overhead to the given structure X,
// although this varies across library container implementations (platforms).
// It is believed that some containers use two pointers per node, so this
// generates a conservative memory usage estimate (it may be slightly too high).
template<typename X>
struct unordered_node : private X
{
private:
void* ptr;
void* ptr_back;
void* ptr_forward;
};

template<typename X, typename Y>
Expand Down
2 changes: 1 addition & 1 deletion src/test/validation_flush_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
// (prevector<28, unsigned char>) when assigned 56 bytes of data per above.
//
// See also: Coin::DynamicMemoryUsage().
constexpr unsigned int COIN_SIZE = is_64_bit ? 80 : 64;
constexpr size_t COIN_SIZE{64};

auto print_view_mem_usage = [](CCoinsViewCache& view) {
BOOST_TEST_MESSAGE("CCoinsViewCache memory usage: " << view.DynamicMemoryUsage());
Expand Down

0 comments on commit c6cba06

Please sign in to comment.