#include <stdlib.h>
using ::nlib_ns::threading::Thread;
#if defined(NN_PLATFORM_CTR)
static const int kRepeatConst = 1;
#elif defined(CAFE)
static const int kRepeatConst = 10;
#else
static const int kRepeatConst = 100;
#endif
class Malloc8Bytes {
public:
Malloc8Bytes(void* (*malloc_func)(size_t), void (*free_func)(void*))
: malloc_(malloc_func), free_(free_func) {}
bool operator()() {
bool success = true;
for (int loop_cnt = 0; loop_cnt < 50; ++loop_cnt) {
const size_t n = kRepeatConst * 1000;
void** ptrs = (void**)malloc_(n * sizeof(void*));
if (!ptrs) return false;
memset(ptrs, 0, n * sizeof(void*));
for (size_t i = 0; i < n; ++i) {
ptrs[i] = malloc_(8);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; ++i) {
free_(ptrs[i]);
}
free_(ptrs);
if (!success) return false;
}
return true;
}
private:
void* (*malloc_)(size_t);
void (*free_)(void*);
};
class MallocFragmentation {
public:
MallocFragmentation(void* (*malloc_func)(size_t), void (*free_func)(void*))
: malloc_(malloc_func), free_(free_func) {}
bool operator()() {
const int nloop = kRepeatConst * 30;
bool success = true;
for (int loop_cnt = 0; loop_cnt < nloop; ++loop_cnt) {
const size_t n = 10000;
void** ptrs = (void**)malloc_(n * sizeof(void*));
if (!ptrs) return false;
memset(ptrs, 0, n * sizeof(void*));
for (size_t i = 0; i < n; ++i) {
ptrs[i] = malloc_(8);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; i += 2) {
free_(ptrs[i]);
ptrs[i] = NULL;
}
for (size_t i = 0; i < n; i += 2) {
ptrs[i] = malloc_(16);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; ++i) {
free_(ptrs[i]);
}
free_(ptrs);
if (!success) return false;
}
return true;
}
private:
void* (*malloc_)(size_t);
void (*free_)(void*);
};
class MallocRealloc {
public:
MallocRealloc(void* (*realloc_func)(void*, size_t), void (*free_func)(void*))
: realloc_(realloc_func), free_(free_func) {}
bool operator()() {
for (int loop_cnt = 0; loop_cnt < kRepeatConst; ++loop_cnt) {
const size_t n = 100000;
void* p = NULL;
for (size_t i = 1; i < n; ++i) {
void* pnew = realloc_(p, i);
if (!pnew) {
free_(p);
return false;
}
p = pnew;
}
free_(p);
}
return true;
}
private:
void* (*realloc_)(void*, size_t);
void (*free_)(void*);
};
const int kNumThread = 10;
Thread g_th[kNumThread];
volatile bool g_success;
class MtSmallMem {
public:
MtSmallMem(void* malloc_func(size_t), void free_func(void*))
: malloc_(malloc_func), free_(free_func) {}
void operator()() {
const int n = 1000;
void* p[n];
for (int j = 0; j < kRepeatConst * 10; ++j) {
for (int i = 0; i < n; ++i) {
p[i] = malloc_(8);
if (!p[i]) g_success = false;
}
for (int i = 0; i < n; ++i) {
free_(p[i]);
}
}
}
private:
void* (*malloc_)(size_t);
void (*free_)(void*);
};
class MtLargeMem {
public:
MtLargeMem(void* malloc_func(size_t), void free_func(void*))
: malloc_(malloc_func), free_(free_func) {}
void operator()() {
const int n = 40;
void* p[n];
for (int j = 0; j < kRepeatConst * 10; ++j) {
for (int i = 0; i < n; ++i) {
p[i] = malloc_(16384);
if (!p[i]) g_success = false;
}
for (int i = 0; i < n; ++i) {
free_(p[i]);
}
}
}
private:
void* (*malloc_)(size_t);
void (*free_)(void*);
};
template<class FUNC>
class MallocMt {
public:
explicit MallocMt(const FUNC& obj) : obj_(obj) {}
bool operator()() {
g_success = true;
for (int i = 0; i < kNumThread; ++i) {
g_th[i].Start(obj_);
}
for (int i = 0; i < kNumThread; ++i) {
g_th[i].Join();
}
return g_success;
}
private:
FUNC obj_;
};
class MutexLoop {
public:
bool operator()() {
for (int i = 0; i < kRepeatConst * 50000; ++i) {
}
return true;
}
};
static void* g_Ptr = NULL;
class NmallocLoop {
public:
bool operator()() {
for (int i = 0; i < kRepeatConst * 50000; ++i) {
}
return true;
}
};
template<class FUNC>
class DoTest {
public:
DoTest(const char* title, const FUNC& func) : title_(title), func_(func) {}
bool operator()() {
bool result = func_();
nlib_printf(
"%s: %" PRIu64
" msec\n", title_, to - from);
return result;
}
private:
const char* title_;
FUNC func_;
};
static bool ClearCache() {
int isclean;
if (!isclean) {
return false;
}
return true;
}
static bool CompareSpeed() {
bool result;
result = DoTest<Malloc8Bytes>("malloc: Malloc8Bytes() loop",
Malloc8Bytes(malloc, free))();
if (!result) return false;
result = DoTest<Malloc8Bytes>("nmalloc: Malloc8Bytes() loop",
if (!result) return false;
if (!ClearCache()) return false;
result = DoTest<MallocFragmentation>("malloc: MallocFragmentation() loop",
MallocFragmentation(malloc, free))();
if (!result) return false;
result = DoTest<MallocFragmentation>("nmalloc: MallocFragmentation() loop",
if (!result) return false;
if (!ClearCache()) return false;
result = DoTest<MallocRealloc>("malloc: realloc() loop",
MallocRealloc(realloc, free))();
if (!result) return false;
result = DoTest<MallocRealloc>("nmalloc: realloc() loop",
if (!result) return false;
if (!ClearCache()) return false;
result = DoTest<MallocMt<MtSmallMem> >(
"malloc: mt-small loop",
MallocMt<MtSmallMem>(MtSmallMem(malloc, free)))();
if (!result) return false;
result = DoTest<MallocMt<MtSmallMem> >(
"nmalloc: mt-small loop",
if (!result) return false;
if (!ClearCache()) return false;
result = DoTest<MallocMt<MtLargeMem> >(
"malloc: mt-large loop",
MallocMt<MtLargeMem>(MtLargeMem(malloc, free)))();
if (!result) return false;
result = DoTest<MallocMt<MtLargeMem> >(
"nmalloc: mt-large loop",
if (!result) return false;
if (!ClearCache()) return false;
result = DoTest<MutexLoop>("nlib_mutex: lock/unlock loop", MutexLoop())();
result = DoTest<NmallocLoop>("nmalloc: nmalloc/nfree loop", NmallocLoop())();
return true;
}
#ifdef NLIB_HAS_VIRTUALMEMORY
settings->
size = 1024 * 1024 * 10;
}
#else
const size_t heapmem_size = 1024 * 1024 * 10;
settings->
addr = heapmem;
settings->
size = heapmem_size;
}
#endif
static bool SampleMain(int, char**) { return CompareSpeed(); }
NLIB_MAINFUNC