Added a buffer counting to the synth in order to track memory
This commit is contained in:
parent
056337b5f0
commit
d849d4f8b7
1 changed files with 71 additions and 10 deletions
|
|
@ -29,20 +29,65 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
namespace sfz
|
namespace sfz
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A heap buffer structure that tries to align its beginning and adds a small offset
|
* @brief A buffer counting class that tries to track the memory usage.
|
||||||
* at the end for alignment too.
|
*/
|
||||||
|
class BufferCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BufferCounter() = default;
|
||||||
|
~BufferCounter()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "Remaining buffers on destruction: " << numBuffers << '\n';
|
||||||
|
std::cout << "Total size: " << bytes << '\n';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void newBuffer(int size)
|
||||||
|
{
|
||||||
|
numBuffers++;
|
||||||
|
bytes.fetch_add(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferResized(int oldSize, int newSize)
|
||||||
|
{
|
||||||
|
bytes.fetch_add(newSize);
|
||||||
|
bytes.fetch_sub(oldSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferDeleted(int size)
|
||||||
|
{
|
||||||
|
numBuffers--;
|
||||||
|
bytes.fetch_sub(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getNumBuffers() { return numBuffers; }
|
||||||
|
int getTotalBytes() { return bytes; }
|
||||||
|
private:
|
||||||
|
std::atomic<int> numBuffers { 0 };
|
||||||
|
std::atomic<int> bytes { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A heap buffer structure that tries to align its beginning and
|
||||||
|
* adds a small offset at the end for alignment too.
|
||||||
*
|
*
|
||||||
* Apparently on Linux this effort is mostly useless, and in the end most of the SIMD operations
|
* Apparently on Linux this effort is mostly useless, and in the end
|
||||||
* are coded with alignment checks and sentinels so this class could probably be much simpler.
|
* most of the SIMD operations are coded with alignment checks and
|
||||||
* It does however wrap realloc which in some cases should be a bit more efficient than
|
* sentinels so this class could probably be much simpler. It does
|
||||||
* allocating a whole new block.
|
* however wrap realloc which in some cases should be a bit more
|
||||||
|
* efficient than allocating a whole new block.
|
||||||
*
|
*
|
||||||
* @tparam Type The buffer type
|
* @tparam Type The buffer type
|
||||||
* @tparam Alignment the required alignment in bytes (defaults to SIMDConfig::defaultAlignment)
|
* @tparam Alignment the required alignment in bytes (defaults to
|
||||||
|
* SIMDConfig::defaultAlignment)
|
||||||
*/
|
*/
|
||||||
template <class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
template <class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
||||||
class Buffer {
|
class Buffer {
|
||||||
|
|
@ -64,7 +109,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Buffer()
|
Buffer()
|
||||||
{
|
{
|
||||||
|
counter().newBuffer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,6 +119,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Buffer(size_t size)
|
Buffer(size_t size)
|
||||||
{
|
{
|
||||||
|
counter().newBuffer(0);
|
||||||
resize(size);
|
resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,6 +144,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counter().bufferResized(largerSize * sizeof(value_type), tempSize * sizeof(value_type));
|
||||||
largerSize = tempSize;
|
largerSize = tempSize;
|
||||||
alignedSize = newSize;
|
alignedSize = newSize;
|
||||||
paddedData = static_cast<pointer>(newData);
|
paddedData = static_cast<pointer>(newData);
|
||||||
|
|
@ -118,6 +165,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
counter().bufferResized(largerSize * sizeof(value_type), 0);
|
||||||
largerSize = 0;
|
largerSize = 0;
|
||||||
alignedSize = 0;
|
alignedSize = 0;
|
||||||
std::free(paddedData);
|
std::free(paddedData);
|
||||||
|
|
@ -127,6 +175,7 @@ public:
|
||||||
}
|
}
|
||||||
~Buffer()
|
~Buffer()
|
||||||
{
|
{
|
||||||
|
counter().bufferDeleted(largerSize * sizeof(value_type));
|
||||||
std::free(paddedData);
|
std::free(paddedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,6 +243,18 @@ public:
|
||||||
constexpr pointer alignedEnd() noexcept { return _alignedEnd; }
|
constexpr pointer alignedEnd() noexcept { return _alignedEnd; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the buffer counter object.
|
||||||
|
*
|
||||||
|
* TODO: In C++ 17 all of this can be static inline.
|
||||||
|
*
|
||||||
|
* @return The buffer counter on which you can call various methods.
|
||||||
|
*/
|
||||||
|
static BufferCounter& counter()
|
||||||
|
{
|
||||||
|
static BufferCounter counter;
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
static constexpr auto AlignmentMask { Alignment - 1 };
|
static constexpr auto AlignmentMask { Alignment - 1 };
|
||||||
static constexpr auto TypeAlignment { Alignment / sizeof(value_type) };
|
static constexpr auto TypeAlignment { Alignment / sizeof(value_type) };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue