#include "ObjectAllocator.h"
#include <iostream>
#include <cstdio>
//#include <typeinfo>
struct PerClassStatistics {
PerClassStatistics() :
num_operator_new_calls(0),
num_operator_delete_calls(0),
num_max_allocated(0) {}
unsigned num_operator_new_calls;
unsigned num_operator_delete_calls;
unsigned num_max_allocated; //max number of concurrent allocations
};
#define USE_ALLOCATOR
////////////////////////////////////////////////////////////////////////////////
#define MMS(CN,Config) \
public: \
static void *operator new(size_t) { \
if (Config::DebugOn) { \
if ( (++stats.num_operator_new_calls-stats.num_operator_delete_calls) \
> stats.num_max_allocated) { \
stats.num_max_allocated = \
stats.num_operator_new_calls-stats.num_operator_delete_calls; \
}\
} \
return ObjectAllocator< sizeof(CN), Config>::Allocate(); \
} \
static void operator delete(void *object) { \
if (Config::DebugOn) /* now check delete NULL*/\
if (object) ++stats.num_operator_delete_calls; \
ObjectAllocator< sizeof(CN), Config>::Free(object); \
} \
static unsigned MMAllocations() { return OAStatsPerSize<sizeof(CN)>::Allocations(); } \
static unsigned MMDeallocations() { return OAStatsPerSize<sizeof(CN)>::Deallocations(); } \
static unsigned MMAllocated() { return OAStatsPerSize<sizeof(CN)>::Allocated(); } \
static unsigned MMAllocatedMax() { return OAStatsPerSize<sizeof(CN)>::MostAllocated(); } \
static void MemManagerConfig() { \
ObjectAllocator< sizeof(CN), Config>::PrintConfig(std::cout); \
} \
static unsigned Allocations() { return stats.num_operator_new_calls; } \
static unsigned Deallocations() { return stats.num_operator_delete_calls; } \
static unsigned Allocated() { return stats.num_operator_new_calls-stats.num_operator_delete_calls; } \
static unsigned AllocatedMax() { return stats.num_max_allocated; } \
private: \
static PerClassStatistics stats; //does not change the size of the class CN!!!!
////////////////////////////////////////////////////////////////////////////////
#define MMS_EXTRA(CN,Config) PerClassStatistics CN::stats;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#define QUOTEME(x) #x
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#define NOMMS(CN,Config) \
public: \
static void MemManagerStats() { \
std::cout << "Class " + #CN + " uses built-in memory manager\n"; \
} \
static void MemManagerConfig() { \
std::cout << "Class" << #CN << " uses built-in memory manager\n"; \
} \
static unsigned MMAllocations() { return OAStatsPerSize<sizeof(CN)>::Allocations(); } \
static unsigned MMDeallocations() { return OAStatsPerSize<sizeof(CN)>::Deallocations(); } \
static unsigned MMAllocated() { return OAStatsPerSize<sizeof(CN)>::Allocated(); } \
static unsigned MMAllocatedMax() { return OAStatsPerSize<sizeof(CN)>::MostAllocated(); } \
static unsigned Allocations() { return 0; } \
static unsigned Deallocations() { return 0; } \
static unsigned Allocated() { return 0; } \
static unsigned AllocatedMax() { return 0; } \
private:
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Alignment PadBytes HeaderBlocks ObjectsPerPage MaxPages DebugOn UseCPPMemManager
//typedef Config<8,0,0,1000,10000,false,true> MyConfig;
typedef Config<8,0,0,20,10000,true,false> MyConfig;
////////////////////////////////////////////////////////////////////////////////
class C {
///////////////////////////////////////////
// memory manager related methods and data
#ifdef USE_ALLOCATOR
MMS(C,MyConfig)
#else
NOMMS(C,MyConfig)
#endif
///////////////////////////////////////////
private:
int i,j;
double d;
public:
C() : i(0),j(0),d(0.0){ /*std::cout << "C()\n";*/ }
C(C const& rhs) : i(rhs.i),j(rhs.j),d(rhs.d){ /*std::cout << "C(C const&)\n";*/ }
};
#ifdef USE_ALLOCATOR
MMS_EXTRA(C,MyConfig)
#endif
class D {
///////////////////////////////////////////
// memory manager related methods and data
#ifdef USE_ALLOCATOR
MMS(D,MyConfig)
#else
NOMMS(D,MyConfig)
#endif
///////////////////////////////////////////
public:
int i,j,k,l;
D() : i(0),j(0),k(0),l(0) { /*std::cout << "D()\n";*/ }
};
#ifdef USE_ALLOCATOR
MMS_EXTRA(D,MyConfig)
#endif
int main1() {
std::cout << "sizeof(C) = " << sizeof(C) << std::endl;
std::cout << "sizeof(D) = " << sizeof(D) << std::endl;
std::cout << "sizeof(PerClassStatistics) = " << sizeof(PerClassStatistics) << std::endl;
C* p1 = new C;
C* p2 = new C(*p1);
C* p3 = new C;
C* p4 = new C;
C* p5 = new C;
C c1,c2;
delete p1;
delete p2;
D* p6 = new D;
D* p7 = new D;
std::cout << "Class C:\n";
std::cout << " Allocations " << C::Allocations() << std::endl;
std::cout << " Deallocations " << C::Deallocations() << std::endl;
std::cout << " Allocated " << C::Allocated() << std::endl;
std::cout << " AllocatedMax " << C::AllocatedMax() << std::endl;
std::cout << "Class D:\n";
std::cout << " Allocations " << D::Allocations() << std::endl;
std::cout << " Deallocations " << D::Deallocations() << std::endl;
std::cout << " Allocated " << D::Allocated() << std::endl;
std::cout << " AllocatedMax " << D::AllocatedMax() << std::endl;
delete p3;
delete p4;
delete p5;
delete p6;
delete p7;
return 0;
}
#include <random>
#include <set>
#include <chrono>
#include <new>
template < typename T >
struct Mallocator {
typedef T value_type;
Mallocator() {
std::cout << "Allocator for " << typeid(T).name() << std::endl;
}
// template <typename U> constexpr Mallocator(const Mallocator<U>&) noexcept {}
/*[[nodiscard]] c++20 */ T* allocate(std::size_t n) {
if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc();
if( auto p = static_cast<T*>(
//std::malloc(n*sizeof(T))
ObjectAllocator< sizeof(T), MyConfig>::Allocate() // only works for single object
)) {
//std::cout << "allocate " << sizeof(T) << "\n";
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t) noexcept {
//std::cout << "de-allocate\n";
//std::free(p);
ObjectAllocator< sizeof(T), MyConfig>::Free( p );
}
};
int main() {
int const array_size = 1000;
C* pC[array_size];
D* pD[array_size];
for ( int i=0; i<array_size; ++i ) {
pC[i] = nullptr;
pD[i] = nullptr;
}
std::default_random_engine generator;
std::uniform_int_distribution<int> rb(0,1); // 0 or 1
std::uniform_int_distribution<int> position(0,array_size-1); // position
for (int i=0;i<10000;++i) {
unsigned pos = position(generator);
unsigned which = rb(generator);
if (which==0) {
delete pC[pos];
pC[pos] = new C;
} else {
delete pD[pos];
pD[pos] = new D;
}
}
// D::MemManagerConfig();
std::cout << "Size " << sizeof(C) << ":\n";
std::cout << " Allocations " << C::MMAllocations() << std::endl;
std::cout << " Deallocations " << C::MMDeallocations() << std::endl;
std::cout << " Allocated " << C::MMAllocated() << std::endl;
std::cout << " AllocatedMax " << C::MMAllocatedMax() << std::endl;
std::cout << "Size " << sizeof(D) << ":\n";
std::cout << " Allocations " << D::MMAllocations() << std::endl;
std::cout << " Deallocations " << D::MMDeallocations() << std::endl;
std::cout << " Allocated " << D::MMAllocated() << std::endl;
std::cout << " AllocatedMax " << D::MMAllocatedMax() << std::endl;
std::cout << "Class C:\n";
std::cout << " Allocations " << C::Allocations() << std::endl;
std::cout << " Deallocations " << C::Deallocations() << std::endl;
std::cout << " Allocated " << C::Allocated() << std::endl;
std::cout << " AllocatedMax " << C::AllocatedMax() << std::endl;
std::cout << "Class D:\n";
std::cout << " Allocations " << D::Allocations() << std::endl;
std::cout << " Deallocations " << D::Deallocations() << std::endl;
std::cout << " Allocated " << D::Allocated() << std::endl;
std::cout << " AllocatedMax " << D::AllocatedMax() << std::endl;
std::chrono::time_point<std::chrono::system_clock> start = std::chrono::system_clock::now();
using MySet = std::set<int, std::less<int>, Mallocator<int>>;
MySet s;
int num_iter = 10000000;
int range = 1000;
std::uniform_int_distribution<int> value(0,range);
for ( int i=0;i<num_iter;++i ) {
int val = value(generator);
unsigned which = rb(generator);
if (which==0) {
MySet::const_iterator it = s.find(val);
if ( it != s.end() ) {
s.erase( it );
}
} else {
s.insert( val );
}
}
std::chrono::time_point<std::chrono::system_clock> end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "time elapsed " << elapsed_seconds.count() << std::endl;
std::cout << "Size " << 40 << ":\n";
std::cout << " Allocations " << OAStatsPerSize<40>::Allocations() << std::endl;
std::cout << " Deallocations " << OAStatsPerSize<40>::Deallocations() << std::endl;
std::cout << " Allocated " << OAStatsPerSize<40>::Allocated() << std::endl;
start = std::chrono::system_clock::now();
using MySet2 = std::set<int, std::less<int>>;
MySet2 s2;
for ( int i=0;i<num_iter;++i ) {
int val = value(generator);
unsigned which = rb(generator);
if (which==0) {
MySet2::const_iterator it = s2.find(val);
if ( it != s2.end() ) {
s2.erase( it );
}
} else {
s2.insert( val );
}
}
end = std::chrono::system_clock::now();
elapsed_seconds = end-start;
std::cout << "time elapsed " << elapsed_seconds.count() << std::endl;
}
// do debug/statistics
//Size 16:
// Allocations 0
// Deallocations 0
// Allocated 0
// AllocatedMax 0
//Size 16:
// Allocations 0
// Deallocations 0
// Allocated 0
// AllocatedMax 0
//Class C:
// Allocations 0
// Deallocations 0
// Allocated 0
// AllocatedMax 0
//Class D:
// Allocations 0
// Deallocations 0
// Allocated 0
// AllocatedMax 0
//Allocator for St13_Rb_tree_nodeIiE
//time elapsed 1.09962
//Size 40:
// Allocations 0
// Deallocations 0
// Allocated 0
//time elapsed 1.21435
//
// with statistics
//Size 16:
// Allocations 10000
// Deallocations 8014
// Allocated 1986
// AllocatedMax 1986
//Size 16:
// Allocations 10000
// Deallocations 8014
// Allocated 1986
// AllocatedMax 1986
//Class C:
// Allocations 4981
// Deallocations 3987
// Allocated 994
// AllocatedMax 994
//Class D:
// Allocations 5019
// Deallocations 4027
// Allocated 992
// AllocatedMax 992
//Allocator for St13_Rb_tree_nodeIiE
//time elapsed 1.51597
//Size 40:
// Allocations 2500946
// Deallocations 2500431
// Allocated 515
//time elapsed 1.22748