Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Created May 18, 2018 17:46
Show Gist options
  • Select an option

  • Save SeijiEmery/c930f84d3ef01d1e33b14822183b45dd to your computer and use it in GitHub Desktop.

Select an option

Save SeijiEmery/c930f84d3ef01d1e33b14822183b45dd to your computer and use it in GitHub Desktop.
// utility/util/mem_bench.hpp
// Copyright (C) 2017 Seiji Emery
//
// 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 by compiling with -D NO_MEM_DEBUG.
//
#pragma once
#ifndef NO_MEM_DEBUG
#include <chrono>
#include <iostream>
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";
}
size_t memAllocated () const { return allocatedMem; }
size_t memDeallocated () const { return freedMem; }
size_t allocCount () const { return numAllocations; }
size_t deallocCount () const { return numFrees; }
} 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