Last active
October 5, 2017 10:25
-
-
Save SeijiEmery/3af0b7ddd08ca1cc3257dd4b8f93cb4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Memory + time benchmarking code: this hijacks (overloads) global new / delete | |
// to trace memory allocations (very simple: # of allocations / frees + # bytes | |
// allocated / freed), and adds a global variable that displays this stuff | |
// from its dtor (guaranteed to be called after main() but before program exits). | |
// | |
// It also adds basic time profiling (global ctor / dtor) using std::chrono. | |
// | |
// All of this can be achieved externally ofc using time + valgrind (*nix), | |
// and is perhaps preferable - but implementing these interally was an interesting | |
// exercise nevertheless. | |
// | |
// This can all be disabled if compiling with -D NO_MEM_DEBUG. | |
// | |
#ifndef NO_MEM_DEBUG | |
#include <chrono> | |
struct MemTracer { | |
void traceAlloc (size_t bytes) { ++numAllocations; allocatedMem += bytes; } | |
void traceFreed (size_t bytes) { ++numFrees; freedMem += bytes;} | |
private: | |
size_t numAllocations = 0; // number of allocations in this program | |
size_t numFrees = 0; // number of deallocations in this program | |
size_t allocatedMem = 0; // bytes allocated | |
size_t freedMem = 0; // bytes freed | |
std::chrono::high_resolution_clock::time_point t0; // time at program start | |
public: | |
MemTracer () : t0(std::chrono::high_resolution_clock::now()) {} | |
~MemTracer () { | |
using namespace std::chrono; | |
auto t1 = high_resolution_clock::now(); | |
std::cout << "\nUsed memory: " << ((double)allocatedMem) * 1e-6 << " MB (" << numAllocations << " allocations)\n"; | |
std::cout << "Freed memory: " << ((double)freedMem) * 1e-6 << " MB (" << numFrees << " deallocations)\n"; | |
std::cout << "Ran in " << duration_cast<duration<double>>(t1 - t0).count() * 1e3 << " ms\n"; | |
} | |
} g_memTracer; | |
void* operator new (size_t size) throw(std::bad_alloc) { | |
g_memTracer.traceAlloc(size); | |
size_t* mem = (size_t*)std::malloc(size + sizeof(size_t)); | |
if (!mem) { | |
throw std::bad_alloc(); | |
} | |
mem[0] = size; | |
return (void*)(&mem[1]); | |
} | |
void operator delete (void* mem) throw() { | |
auto ptr = &((size_t*)mem)[-1]; | |
g_memTracer.traceFreed(ptr[0]); | |
std::free(ptr); | |
} | |
#endif // NO_MEM_DEBUG |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: this is NOT threadsafe – though it could be made threadsafe by using atomic operations.