forked from ned14/nedmalloc
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)
committed
Jul 14, 2010
1 parent
2743c75
commit f3624af
Showing
7 changed files
with
548 additions
and
3 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* scalingtest.cpp | ||
Tests how various allocators scale according to block size using a monte-carlo approach | ||
(C) 2010 Niall Douglas | ||
*/ | ||
|
||
#define FORCEINLINE | ||
#define NOINLINE | ||
//#define THREADCACHEMAX 0 | ||
//#pragma optimize("g", off) | ||
|
||
#include "nedmalloc.c" | ||
#include <math.h> | ||
#include <vector> | ||
|
||
#define LOOPS 25000 | ||
#define MAXBLOCKSIZE (8*1024*1024) | ||
|
||
#ifdef WIN32 | ||
typedef unsigned __int64 usCount; | ||
static usCount GetUsCount() | ||
{ | ||
static LARGE_INTEGER ticksPerSec; | ||
static double scalefactor; | ||
LARGE_INTEGER val; | ||
if(!scalefactor) | ||
{ | ||
if(QueryPerformanceFrequency(&ticksPerSec)) | ||
scalefactor=ticksPerSec.QuadPart/1000000000000.0; | ||
else | ||
scalefactor=1; | ||
} | ||
if(!QueryPerformanceCounter(&val)) | ||
return (usCount) GetTickCount() * 1000000000; | ||
return (usCount) (val.QuadPart/scalefactor); | ||
} | ||
#else | ||
#include <sys/time.h> | ||
|
||
typedef unsigned long long usCount; | ||
static usCount GetUsCount() | ||
{ | ||
#ifdef CLOCK_MONOTONIC | ||
struct timespec ts; | ||
clock_gettime(CLOCK_MONOTONIC, &ts); | ||
return ((usCount) ts.tv_sec*1000000000000LL)+ts.tv_nsec*1000LL; | ||
#else | ||
struct timeval tv; | ||
gettimeofday(&tv, 0); | ||
return ((usCount) tv.tv_sec*1000000000000LL)+tv.tv_usec*1000000LL; | ||
#endif | ||
} | ||
#endif | ||
|
||
template<void (*_free)(void *)> void wrapfree(void *mem, size_t size) | ||
{ | ||
_free(mem); | ||
} | ||
static void *mmap_wrapper(size_t size) | ||
{ | ||
#ifdef WIN32 | ||
return VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); | ||
#else | ||
return mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | ||
#endif | ||
} | ||
static void munmap_wrapper(void *mem, size_t size) | ||
{ | ||
#ifdef WIN32 | ||
VirtualFree(mem, 0, MEM_RELEASE); | ||
#else | ||
munmap(mem, size); | ||
#endif | ||
} | ||
static void *userpagemalloc_wrapper(size_t size) | ||
{ | ||
return userpage_malloc(size, 0); | ||
} | ||
static void userpagefree_wrapper(void *mem, size_t size) | ||
{ | ||
userpage_free(mem, size); | ||
} | ||
static mspace mymspace = create_mspace(0,0); | ||
static void *dlmalloc(size_t size) | ||
{ | ||
return mspace_malloc(mymspace, size); | ||
} | ||
static void dlfree(void *mem, size_t size) | ||
{ | ||
mspace_free(mymspace, mem); | ||
} | ||
|
||
struct Allocator | ||
{ | ||
const char *name, *shortname; | ||
size_t minsize, minsizeshift; | ||
void *(*malloc)(size_t); | ||
void (*free)(void *, size_t); | ||
}; | ||
static Allocator allocators[]={ | ||
{ "System allocator", "sysalloc", 0, 0, &malloc, &wrapfree<free> }, | ||
{ "nedmalloc", "nedmalloc", 0, 0, &nedalloc::nedmalloc, &wrapfree<nedalloc::nedfree> }, | ||
{ "dlmalloc", "dlmalloc", 0, 0, &dlmalloc, &dlfree }, | ||
#ifndef WIN32 | ||
{ "System mmap()", "sysmmap", PAGE_SIZE, 0, &mmap_wrapper, &munmap_wrapper }, | ||
#else | ||
{ "System VirtualAlloc()", "sysmmap", PAGE_SIZE, 0, &mmap_wrapper, &munmap_wrapper }, | ||
#endif | ||
{ "User mode page allocator", "usermodemmap", PAGE_SIZE, 0, &userpagemalloc_wrapper, &userpagefree_wrapper } | ||
}; | ||
|
||
int main(void) | ||
{ | ||
using namespace std; | ||
printf("What would you like to test?\n"); | ||
for(int n=0; n<sizeof(allocators)/sizeof(Allocator); n++) | ||
{ | ||
printf(" %d. %s\n", n+1, allocators[n].name); | ||
} | ||
int allocatoridx=getchar()-'1'; | ||
if(allocatoridx<0 || allocatoridx>sizeof(allocators)/sizeof(Allocator)) return 1; | ||
Allocator &allocator=allocators[allocatoridx]; | ||
allocator.minsizeshift=allocator.minsize ? nedtriebitscanr(allocator.minsize) : (allocator.minsize=1<<3, 3); | ||
printf("\nYou chose allocator %d (%s) with minsizeshift=%u\n", allocatoridx+1, allocator.name, allocator.minsizeshift); | ||
for(usCount s=GetUsCount(); GetUsCount()-s<3000000000000ULL;); | ||
printf("Testing ...\n"); | ||
|
||
vector<pair<usCount, size_t> > bins(nedtriebitscanr(MAXBLOCKSIZE)+1); | ||
struct Ptrs_t { void *mem; size_t size; } ptrs[512], *ptrp; | ||
memset(ptrs, 0, sizeof(ptrs)); | ||
ptrp=ptrs; | ||
for(int n=0; n<LOOPS; n++) | ||
{ | ||
size_t blksize; | ||
do | ||
{ | ||
double randval=(double) rand()/(RAND_MAX/(8*sizeof(size_t)))+allocator.minsizeshift; | ||
blksize=((size_t) pow(2, randval)) & (MAXBLOCKSIZE-1); | ||
blksize&=~(allocator.minsize-1); | ||
} while(blksize<allocator.minsize); | ||
usCount start, end; | ||
if(n>LOOPS/2 && blksize<32) | ||
{ | ||
int a=1; | ||
} | ||
if(ptrp->mem) | ||
{ | ||
start=GetUsCount(); | ||
allocator.free(ptrp->mem, ptrp->size); | ||
end=GetUsCount(); | ||
//pair<usCount, size_t> &v=bins[nedtriebitscanr(ptrp->size)]; | ||
//v.first+=end-start; | ||
//v.second++; | ||
ptrp->mem=0; ptrp->size=0; | ||
} | ||
start=GetUsCount(); | ||
ptrp->mem=allocator.malloc(blksize); | ||
ptrp->size=blksize; | ||
for(volatile char *p=(volatile char *)ptrp->mem, *pend=(volatile char *)ptrp->mem+blksize; p<pend; p+=PAGE_SIZE) | ||
*p; | ||
end=GetUsCount(); | ||
if(++ptrp==ptrs+512) ptrp=ptrs; | ||
pair<usCount, size_t> &v=bins[blksize ? nedtriebitscanr(blksize) : 0]; | ||
v.first+=end-start; | ||
v.second++; | ||
} | ||
char filename[256]; | ||
sprintf(filename, "scalingtest_%s.csv", allocator.shortname); | ||
printf("\nWriting results to %s ...\n", filename); | ||
FILE *oh=fopen(filename, "w"); | ||
fprintf(oh, "Bin,Latency,Count\n"); | ||
int n=0; | ||
for(vector<pair<usCount, size_t> >::const_iterator it=bins.begin(); it!=bins.end(); ++it, n++) | ||
{ | ||
fprintf(oh, "%u,%f,%u\n", 1<<n, (double) it->first/it->second, it->second); | ||
} | ||
fclose(oh); | ||
printf("Done!\n"); | ||
return 0; | ||
} |
Oops, something went wrong.