| 84 | class MemPool; |
| 85 | |
| 86 | class MemoryStats |
| 87 | { |
| 88 | public: |
| 89 | explicit MemoryStats(MemoryStats* parent = NULL) |
| 90 | : mst_parent(parent), mst_usage(0), mst_mapped(0), mst_max_usage(0), mst_max_mapped(0) |
| 91 | {} |
| 92 | |
| 93 | ~MemoryStats() |
| 94 | {} |
| 95 | |
| 96 | size_t getCurrentUsage() const noexcept { return mst_usage.value(); } |
| 97 | size_t getMaximumUsage() const noexcept { return mst_max_usage; } |
| 98 | size_t getCurrentMapping() const noexcept { return mst_mapped.value(); } |
| 99 | size_t getMaximumMapping() const noexcept { return mst_max_mapped; } |
| 100 | |
| 101 | private: |
| 102 | // Forbid copying/assignment |
| 103 | MemoryStats(const MemoryStats&); |
| 104 | MemoryStats& operator=(const MemoryStats&); |
| 105 | |
| 106 | MemoryStats* mst_parent; |
| 107 | |
| 108 | // Currently allocated memory (without allocator overhead) |
| 109 | // Useful for monitoring engine memory leaks |
| 110 | AtomicCounter mst_usage; |
| 111 | // Amount of memory mapped (including all overheads) |
| 112 | // Useful for monitoring OS memory consumption |
| 113 | AtomicCounter mst_mapped; |
| 114 | |
| 115 | // We don't particularily care about extreme precision of these max values, |
| 116 | // this is why we don't synchronize them |
| 117 | size_t mst_max_usage; |
| 118 | size_t mst_max_mapped; |
| 119 | |
| 120 | // These methods are thread-safe due to usage of atomic counters only |
| 121 | void increment_usage(size_t size) noexcept |
| 122 | { |
| 123 | for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) |
| 124 | { |
| 125 | const size_t temp = statistics->mst_usage.exchangeAdd(size) + size; |
| 126 | if (temp > statistics->mst_max_usage) |
| 127 | statistics->mst_max_usage = temp; |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | void decrement_usage(size_t size) noexcept |
| 132 | { |
| 133 | for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) |
| 134 | { |
| 135 | statistics->mst_usage -= size; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | void increment_mapping(size_t size) noexcept |
| 140 | { |
| 141 | for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent) |
| 142 | { |
| 143 | const size_t temp = statistics->mst_mapped.exchangeAdd(size) + size; |