#include <stdlib.h>
using ::nlib_ns::threading::Thread;
#if defined(NN_PLATFORM_CTR)
static const int kRepeatConst = 1;
#elif defined(NLIB_CAFE_PPC)
static const int kRepeatConst = 10;
#else
static const int kRepeatConst = 100;
#endif
class malloc_8bytes {
public:
malloc_8bytes(void* (*malloc_func)(size_t), void (*free_func)(void*))
: m_Malloc(malloc_func), m_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**)m_Malloc(n * sizeof(void*));
if (!ptrs) return false;
memset(ptrs, 0, n * sizeof(void*));
for (size_t i = 0; i < n; ++i) {
ptrs[i] = m_Malloc(8);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; ++i) {
m_Free(ptrs[i]);
}
m_Free(ptrs);
if (!success) return false;
}
return true;
}
private:
void* (*m_Malloc)(size_t);
void (*m_Free)(void*);
};
class malloc_fragmentation {
public:
malloc_fragmentation(void* (*malloc_func)(size_t), void (*free_func)(void*))
: m_Malloc(malloc_func), m_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**)m_Malloc(n * sizeof(void*));
if (!ptrs) return false;
memset(ptrs, 0, n * sizeof(void*));
for (size_t i = 0; i < n; ++i) {
ptrs[i] = m_Malloc(8);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; i += 2) {
m_Free(ptrs[i]);
ptrs[i] = NULL;
}
for (size_t i = 0; i < n; i += 2) {
ptrs[i] = m_Malloc(16);
if (!ptrs[i]) {
success = false;
break;
}
}
for (size_t i = 0; i < n; ++i) {
m_Free(ptrs[i]);
}
m_Free(ptrs);
if (!success) return false;
}
return true;
}
private:
void* (*m_Malloc)(size_t);
void (*m_Free)(void*);
};
class malloc_realloc {
public:
malloc_realloc(void* (*realloc_func)(void*, size_t), void (*free_func)(void*))
: m_Realloc(realloc_func), m_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 = m_Realloc(p, i);
if (!pnew) {
m_Free(p);
return false;
}
p = pnew;
}
m_Free(p);
}
return true;
}
private:
void* (*m_Realloc)(void*, size_t);
void (*m_Free)(void*);
};
const int kNumThread = 10;
Thread g_Th[kNumThread];
volatile bool g_Success;
class mt_smallmem {
public:
mt_smallmem(void* malloc_func(size_t), void free_func(void*))
: m_Malloc(malloc_func), m_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] = m_Malloc(8);
if (!p[i]) g_Success = false;
}
for (int i = 0; i < n; ++i) {
m_Free(p[i]);
}
}
}
private:
void* (*m_Malloc)(size_t);
void (*m_Free)(void*);
};
class mt_largemem {
public:
mt_largemem(void* malloc_func(size_t), void free_func(void*))
: m_Malloc(malloc_func), m_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] = m_Malloc(16384);
if (!p[i]) g_Success = false;
}
for (int i = 0; i < n; ++i) {
m_Free(p[i]);
}
}
}
private:
void* (*m_Malloc)(size_t);
void (*m_Free)(void*);
};
template<class FUNC>
class malloc_mt {
public:
explicit malloc_mt(const FUNC& obj) : m_Obj(obj) {}
bool operator()() {
g_Success = true;
for (int i = 0; i < kNumThread; ++i) {
g_Th[i].Start(m_Obj);
}
for (int i = 0; i < kNumThread; ++i) {
g_Th[i].Join();
}
return g_Success;
}
private:
FUNC m_Obj;
};
class mutex_loop {
public:
bool operator()() {
for (int i = 0; i < kRepeatConst * 50000; ++i) {
}
return true;
}
};
static void* g_Ptr = NULL;
class nmalloc_loop {
public:
bool operator()() {
for (int i = 0; i < kRepeatConst * 50000; ++i) {
}
return true;
}
};
template<class FUNC>
class do_test {
public:
do_test(const char* title, const FUNC& func) : m_Title(title), m_Func(func) {}
bool operator()() {
bool result = m_Func();
nlib_printf(
"%s: %" PRIu64
" msec\n", m_Title, to - from);
return result;
}
private:
const char* m_Title;
FUNC m_Func;
};
static bool clear_cache() {
return false;
}
return true;
}
static bool compare_speed() {
bool result;
result = do_test<malloc_8bytes>("malloc: malloc_8bytes() loop",
malloc_8bytes(malloc, free))();
if (!result) return false;
result = do_test<malloc_8bytes>("nmalloc: malloc_8bytes() loop",
if (!result) return false;
if (!clear_cache()) return false;
result = do_test<malloc_fragmentation>("malloc: malloc_fragmentation() loop",
malloc_fragmentation(malloc, free))();
if (!result) return false;
result = do_test<malloc_fragmentation>("nmalloc: malloc_fragmentation() loop",
if (!result) return false;
if (!clear_cache()) return false;
result = do_test<malloc_realloc>("malloc: realloc() loop",
malloc_realloc(realloc, free))();
if (!result) return false;
result = do_test<malloc_realloc>("nmalloc: realloc() loop",
if (!result) return false;
if (!clear_cache()) return false;
result = do_test<malloc_mt<mt_smallmem> >(
"malloc: mt-small loop",
malloc_mt<mt_smallmem>(mt_smallmem(malloc, free)))();
if (!result) return false;
result = do_test<malloc_mt<mt_smallmem> >(
"nmalloc: mt-small loop",
if (!result) return false;
if (!clear_cache()) return false;
result = do_test<malloc_mt<mt_largemem> >(
"malloc: mt-large loop",
malloc_mt<mt_largemem>(mt_largemem(malloc, free)))();
if (!result) return false;
result = do_test<malloc_mt<mt_largemem> >(
"nmalloc: mt-large loop",
if (!result) return false;
if (!clear_cache()) return false;
result = do_test<mutex_loop>("nlib_mutex: lock/unlock loop", mutex_loop())();
result = do_test<nmalloc_loop>("nmalloc: nmalloc/nfree loop", nmalloc_loop())();
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;
settings->heap_option = 0;
}
#endif
static bool SampleMain(int, char**) { return compare_speed(); }
NLIB_MAINFUNC