mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-08 05:10:41 +01:00
perf(debug): count what the program takes with new (global operator new/delete of the executable) and the objects of the model instances in the memory section of the debug panel
This commit is contained in:
@@ -1174,6 +1174,10 @@ void opengl46_renderer::Update_Memory_Info()
|
|||||||
text += "process: " + mb( process.resident ) + " resident (peak " + mb( process.peak ) + ")"
|
text += "process: " + mb( process.resident ) + " resident (peak " + mb( process.peak ) + ")"
|
||||||
+ ( process.committed > 0 ? ", " + mb( process.committed ) + " private" : std::string{} ) + "\n";
|
+ ( process.committed > 0 ? ", " + mb( process.committed ) + " private" : std::string{} ) + "\n";
|
||||||
}
|
}
|
||||||
|
// what the program took with new: the rest of the private memory is of the drivers, libraries and the c runtime
|
||||||
|
auto const heap { query_heap_memory() };
|
||||||
|
text += "taken with new: " + mb( heap.bytes ) + " in " + std::to_string( heap.blocks ) + " blocks"
|
||||||
|
+ ( process.valid && ( process.committed > heap.bytes ) ? ", the rest of the private memory " + mb( process.committed - heap.bytes ) + " (drivers, libraries)" : std::string{} ) + "\n";
|
||||||
// the memory of the card, all processes: GL_NVX_gpu_memory_info (in kB)
|
// the memory of the card, all processes: GL_NVX_gpu_memory_info (in kB)
|
||||||
if( m_nvxmemory < 0 ) {
|
if( m_nvxmemory < 0 ) {
|
||||||
m_nvxmemory = 0;
|
m_nvxmemory = 0;
|
||||||
@@ -1239,7 +1243,10 @@ void opengl46_renderer::Update_Memory_Info()
|
|||||||
}
|
}
|
||||||
accounted += shapes.bytes + lines.bytes + sleepers.bytes;
|
accounted += shapes.bytes + lines.bytes + sleepers.bytes;
|
||||||
text += "scenery: " + counted( shapes, "shapes" ) + " " + mb( shapes.bytes ) + ", " + counted( lines, "lines" ) + " " + mb( lines.bytes ) + ", sleepers of "
|
text += "scenery: " + counted( shapes, "shapes" ) + " " + mb( shapes.bytes ) + ", " + counted( lines, "lines" ) + " " + mb( lines.bytes ) + ", sleepers of "
|
||||||
+ counted( sleepers, "tracks" ) + " " + mb( sleepers.bytes ) + ", " + std::to_string( instances ) + " model instances\n";
|
+ counted( sleepers, "tracks" ) + " " + mb( sleepers.bytes ) + "\n";
|
||||||
|
// the objects of the model instances themselves, without the strings and the containers they hold
|
||||||
|
accounted += instances * sizeof( TAnimModel );
|
||||||
|
text += "model instances: " + std::to_string( instances ) + ", their objects " + mb( instances * sizeof( TAnimModel ) ) + " (" + std::to_string( sizeof( TAnimModel ) ) + " bytes each)\n";
|
||||||
// sounds: the data of the buffers, which the AL keeps in the process
|
// sounds: the data of the buffers, which the AL keeps in the process
|
||||||
auto const sounds { audio::renderer.buffers_memory() };
|
auto const sounds { audio::renderer.buffers_memory() };
|
||||||
accounted += sounds.bytes;
|
accounted += sounds.bytes;
|
||||||
|
|||||||
@@ -10,16 +10,147 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "utilities/memorystats.h"
|
#include "utilities/memorystats.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#include <malloc.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#pragma comment(lib, "psapi.lib")
|
#pragma comment(lib, "psapi.lib")
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
|
#include <malloc/malloc.h>
|
||||||
#else
|
#else
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <malloc.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// the global new and delete of the executable count the memory of the blocks they hand out (query_heap_memory()). the blocks come
|
||||||
|
// from malloc() as with the default operators; the aligned forms are left to the runtime
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
std::atomic<std::uint64_t> g_heapbytes{0};
|
||||||
|
std::atomic<std::uint64_t> g_heapblocks{0};
|
||||||
|
|
||||||
|
std::size_t block_size(void *Block)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return ::_msize(Block);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
return ::malloc_size(Block);
|
||||||
|
#else
|
||||||
|
return ::malloc_usable_size(Block);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void *counted_new(std::size_t Size)
|
||||||
|
{
|
||||||
|
if (Size == 0)
|
||||||
|
{
|
||||||
|
Size = 1;
|
||||||
|
}
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (auto *block{std::malloc(Size)})
|
||||||
|
{
|
||||||
|
g_heapbytes.fetch_add(block_size(block), std::memory_order_relaxed);
|
||||||
|
g_heapblocks.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
auto const handler{std::get_new_handler()};
|
||||||
|
if (handler == nullptr)
|
||||||
|
{
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void counted_delete(void *Block) noexcept
|
||||||
|
{
|
||||||
|
if (Block == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_heapbytes.fetch_sub(block_size(Block), std::memory_order_relaxed);
|
||||||
|
g_heapblocks.fetch_sub(1, std::memory_order_relaxed);
|
||||||
|
std::free(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void *operator new(std::size_t Size)
|
||||||
|
{
|
||||||
|
return counted_new(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new[](std::size_t Size)
|
||||||
|
{
|
||||||
|
return counted_new(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new(std::size_t Size, std::nothrow_t const &) noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return counted_new(Size);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new[](std::size_t Size, std::nothrow_t const &) noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return counted_new(Size);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *Block) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void *Block) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *Block, std::size_t) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void *Block, std::size_t) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *Block, std::nothrow_t const &) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void *Block, std::nothrow_t const &) noexcept
|
||||||
|
{
|
||||||
|
counted_delete(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_memory query_heap_memory()
|
||||||
|
{
|
||||||
|
return {g_heapbytes.load(std::memory_order_relaxed), g_heapblocks.load(std::memory_order_relaxed)};
|
||||||
|
}
|
||||||
|
|
||||||
process_memory query_process_memory()
|
process_memory query_process_memory()
|
||||||
{
|
{
|
||||||
process_memory result;
|
process_memory result;
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ struct process_memory
|
|||||||
|
|
||||||
process_memory query_process_memory();
|
process_memory query_process_memory();
|
||||||
|
|
||||||
|
// what the program took with new and hasn't given back with delete (the global operators of the executable count it): bytes of
|
||||||
|
// the blocks, as the c runtime made them, and blocks. what libraries, the c runtime and the drivers take otherwise isn't in it
|
||||||
|
struct heap_memory
|
||||||
|
{
|
||||||
|
std::uint64_t bytes{0};
|
||||||
|
std::uint64_t blocks{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
heap_memory query_heap_memory();
|
||||||
|
|
||||||
// what a part of the program keeps in memory: things and bytes
|
// what a part of the program keeps in memory: things and bytes
|
||||||
struct memory_count
|
struct memory_count
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user