int main(void) { int n; usCount start; pthread_permit1_t permit1; printf("Press key to continue ...\n"); getchar(); printf("Wait ...\n"); start=GetUsCount(); while(GetUsCount()-start<3000000000000ULL); printf("Calculating timing overhead ...\n"); for(n=0; n<5000000; n++) { start=GetUsCount(); timingoverhead+=GetUsCount()-start; } timingoverhead/=5000000; printf("Timing overhead on this machine is %u us. Go!\n", (size_t) timingoverhead); pthread_permit1_init(&permit1, 1); permitaddr=&permit1; for(n=0; n<THREADS; n++) { thrd_create(&threads[n], (thrd_start_t) threadfunc<pthread_permit1_t, pthread_permit1_grant, pthread_permit1_revoke, pthread_permit1_wait>, (void *)(size_t)n); } printf("Press key to kill all\n"); getchar(); done=1; mssleep(2000); printf("Press key to exit\n"); getchar(); return 0; }
template<typename permit_t, int (*permit_grant)(pthread_permitX_t), void (*permit_revoke)(permit_t *), int(*permit_wait)(permit_t *, mtx_t *mtx)> int threadfunc(void *mynum) { size_t mythread=(size_t) mynum; permit_t *permit=(permit_t *)permitaddr; usCount start, end; size_t count=0; #ifdef UNCONTENDED if(UNCONTENDED==mythread) return 0; #endif if(!mynum) { usCount revoketotal=0, granttotal=0; while(!done) { #if DONTCONSUME // Revoke permit start=GetUsCount(); permit_revoke(permit); end=GetUsCount(); revoketotal+=end-start-timingoverhead; //printf("Thread %u revoked permit\n", mythread); #endif //mssleep(1000); //printf("\nThread %u granting permit\n", mythread); start=GetUsCount(); permit_grant(permit); end=GetUsCount(); granttotal+=end-start-timingoverhead; //mssleep(1); count++; } printf("Thread %u, average revoke/grant time was %u/%u cycles\n", mythread, (size_t)((double)revoketotal/count*CYCLESPERMICROSECOND), (size_t)((double)granttotal/count*CYCLESPERMICROSECOND)); permit_grant(permit); } else { usCount waittotal=0; mtx_t mtx; mtx_init(&mtx, mtx_plain); mtx_lock(&mtx); while(!done) { // Wait on permit start=GetUsCount(); permit_wait(permit, &mtx); end=GetUsCount(); waittotal+=end-start-timingoverhead; count++; //printf("%u", mythread); #if defined(UNCONTENDED) && 0==DONTCONSUME if(UNCONTENDED==0 && 1==mythread) { permit_grant(permit); } #endif } printf("Thread %u, average wait time was %u cycles\n", mythread, (size_t)((double)waittotal/count*CYCLESPERMICROSECOND)); } return 0; }
int main(void) { double std=0, ned=0; #if 0 { usCount start, end; start=GetUsCount(); THREADSLEEP(5000); end=GetUsCount(); printf("Wait was %lf\n", (end-start)/1000000000000.0); } #endif #ifdef WIN32 { /* Force load of user32.dll so we can debug */ BOOL v; SystemParametersInfo(SPI_GETBEEP, 0, &v, 0); } #endif if(0) { printf("\nTesting standard allocator with %d threads ...\n", THREADS); std=runtest(); } if(1) { printf("\nTesting nedmalloc with %d threads ...\n", THREADS); whichmalloc=1; ned=runtest(); } #ifdef WIN32 if(0) { ULONG data=2; win32heap=HeapCreate(0, 0, 0); HeapSetInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data)); HeapQueryInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data), NULL); if(2!=data) { printf("The win32 low frag allocator won't work under a debugger!\n"); } else { printf("Testing win32 low frag allocator with %d threads ...\n\n", THREADS); whichmalloc=2; runtest(); } HeapDestroy(win32heap); } #endif if(std && ned) { // ned should have more ops/sec printf("\n\nnedmalloc allocator is %lf times faster than standard\n", ned/std); } printf("\nPress a key to trim\n"); getchar(); nedmalloc_trim(0); #ifdef _MSC_VER printf("\nPress a key to end\n"); getchar(); #endif return 0; }
static void threadcode(int threadidx) { int n; unsigned int *toallocptr=threadstuff[threadidx].toalloc; void **allocptr=threadstuff[threadidx].allocs; unsigned int seed=threadidx; usCount start; threadstuff[threadidx].done=0; /*neddisablethreadcache(0);*/ THREADSLEEP(100); start=GetUsCount(); #ifdef TORTURETEST /* A randomised malloc/realloc/free test (torture test) */ for(n=0; n<RECORDS*100; n++) { unsigned int r=myrandom(&seed), i; i=(int)(r % RECORDS); if(!allocptr[i]) { allocptr[i]=mallocs[whichmalloc](r & 0x1FFF); threadstuff[threadidx].ops++; } else if(r & (1<<31)) { allocptr[i]=reallocs[whichmalloc](allocptr[i], r & 0x1FFF); threadstuff[threadidx].ops++; } else { frees[whichmalloc](allocptr[i]); allocptr[i]=0; } } for(n=0; n<RECORDS; n++) { if(allocptr[n]) { frees[whichmalloc](allocptr[n]); allocptr[n]=0; } } #else /* A simple stack which allocates and deallocates off the top (speed test) */ for(n=0; n<RECORDS;) { #if 1 r=myrandom(&seed); if(allocptr>threadstuff[threadidx].allocs && (r & 65535)<32760) /*<32760)*/ { /* free */ --toallocptr; --allocptr; --n; frees[whichmalloc](*allocptr); *allocptr=0; } else #endif { if(doRealloc && allocptr>threadstuff[threadidx].allocs && (r & 1)) { allocptr[-1]=reallocs[whichmalloc](allocptr[-1], *toallocptr); } else { allocptr[0]=mallocs[whichmalloc](*toallocptr); allocptr++; } n++; toallocptr++; threadstuff[threadidx].ops++; } } while(allocptr>threadstuff[threadidx].allocs) { frees[whichmalloc](*--allocptr); } #endif times[threadidx]+=GetUsCount()-start; neddisablethreadcache(0); threadstuff[threadidx].done=1; }
int main(void) { double std=0, ned=0; #if defined(WIN32) && defined(USE_NEDMALLOC_DLL) /*PatchInNedmallocDLL();*/ #endif #if 0 { usCount start, end; start=GetUsCount(); THREADSLEEP(5000); end=GetUsCount(); printf("Wait was %lf\n", (end-start)/1000000000000.0); } #endif #ifdef WIN32 #pragma comment(lib, "user32.lib") { /* Force load of user32.dll so we can debug */ BOOL v; SystemParametersInfo(SPI_GETBEEP, 0, &v, 0); } #endif #if 2==TESTTYPE printf("Running torture test\n" "-=-=-=-=-=-=-=-=-=-=\n"); #elif 1==TESTTYPE printf("Running speed test\n" "-=-=-=-=-=-=-=-=-=\n"); #endif printf("Block size <= %u, C++ test mode is %s\n", BLOCKSIZE, TESTCPLUSPLUS ? "on" : "off"); if(0) { printf("\nTesting standard allocator with %d threads ...\n", THREADS); std=runtest(); } if(1) { printf("\nTesting nedmalloc with %d threads ...\n", THREADS); whichmalloc=1; ned=runtest(); } #ifdef WIN32 if(0) { ULONG data=2; win32heap=HeapCreate(0, 0, 0); HeapSetInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data)); HeapQueryInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data), NULL); if(2!=data) { printf("The win32 low frag allocator won't work under a debugger!\n"); } else { printf("Testing win32 low frag allocator with %d threads ...\n\n", THREADS); whichmalloc=2; runtest(); } HeapDestroy(win32heap); } #endif if(std && ned) { // ned should have more ops/sec printf("\n\nnedmalloc allocator is %lf times faster than standard\n", ned/std); } printf("\nPress a key to trim\n"); getchar(); nedmalloc_trim(0); #ifdef _MSC_VER printf("\nPress a key to end\n"); getchar(); #endif return 0; }
static void threadcode(int threadidx) { int n; unsigned int *toallocptr=threadstuff[threadidx].toalloc; void **allocptr=threadstuff[threadidx].allocs; unsigned int r, seed=threadidx; usCount start; size_t allocated=0, size; threadstuff[threadidx].done=0; /*neddisablethreadcache(0);*/ THREADSLEEP(100); start=GetUsCount(); #if 2==TESTTYPE /* A randomised malloc/realloc/free test (torture test) */ for(n=0; n<RECORDS*100; n++) { static int reallocflip; unsigned int i, dorealloc=(reallocflip=!reallocflip); r=myrandom(&seed); i=(int)(r % RECORDS); #if TESTCPLUSPLUS dorealloc=!(r&(15<<28)); if(r&(1<<31)) { /* Make it two power multiple of less than 512 bytes to model frequent C++ new's */ size=4<<(r & 7); dorealloc=0; } else #endif size=(size_t)(r & (BLOCKSIZE-1)); if(allocated<MAXMEMORY2 && !allocptr[i]) { if(!(allocptr[i]=mallocs[whichmalloc](size))) abort(); #if TOUCH { volatile char *mem=(volatile char *)allocptr[i]; volatile char *end=mem+size; for(; mem<end; mem+=4096) *mem; } #endif allocated+=memsizes[whichmalloc](allocptr[i]); threadstuff[threadidx].ops.mallocs++; } else if(allocated<MAXMEMORY2 && dorealloc) /* If not TESTCPLUSPLUS, then how often realloc() gets called depends on how small RECORDS is. */ { allocated-=memsizes[whichmalloc](allocptr[i]); if(!(allocptr[i]=reallocs[whichmalloc](allocptr[i], size))) abort(); #if TOUCH { volatile char *mem=(volatile char *)allocptr[i]; volatile char *end=mem+size; for(; mem<end; mem+=4096) *mem; } #endif allocated+=memsizes[whichmalloc](allocptr[i]); threadstuff[threadidx].ops.reallocs++; } else if(allocptr[i]) { allocated-=memsizes[whichmalloc](allocptr[i]); frees[whichmalloc](allocptr[i]); allocptr[i]=0; threadstuff[threadidx].ops.frees++; } } for(n=0; n<RECORDS; n++) { if(allocptr[n]) { allocated-=memsizes[whichmalloc](allocptr[n]); frees[whichmalloc](allocptr[n]); allocptr[n]=0; threadstuff[threadidx].ops.frees++; } } assert(!allocated); #elif 1==TESTTYPE /* A simple stack which allocates and deallocates off the top (speed test) */ for(n=0; n<RECORDS;) { #if 1 r=myrandom(&seed); if(allocptr>threadstuff[threadidx].allocs && (r & 65535)<32760) /*<32760)*/ { /* free */ --toallocptr; --allocptr; --n; frees[whichmalloc](*allocptr); *allocptr=0; threadstuff[threadidx].ops.frees++; } else #endif { if(doRealloc && allocptr>threadstuff[threadidx].allocs && (r & 1)) { if(!(allocptr[-1]=reallocs[whichmalloc](allocptr[-1], *toallocptr))) abort(); #if TOUCH { volatile char *mem=(volatile char *)allocptr[-1]; volatile char *end=mem+*toallocptr; for(; mem<end; mem+=4096) *mem; } #endif threadstuff[threadidx].ops.reallocs++; } else { if(!(allocptr[0]=mallocs[whichmalloc](*toallocptr))) abort(); #if TOUCH { volatile char *mem=(volatile char *)allocptr[0]; volatile char *end=mem+*toallocptr; for(; mem<end; mem+=4096) *mem; } #endif threadstuff[threadidx].ops.mallocs++; allocptr++; } n++; toallocptr++; /*if(!(threadstuff[threadidx].ops & 0xff)) nedtrimthreadcache(0,0);*/ } } while(allocptr>threadstuff[threadidx].allocs) { frees[whichmalloc](*--allocptr); threadstuff[threadidx].ops.frees++; } #endif times[threadidx]+=GetUsCount()-start; neddisablethreadcache(0); threadstuff[threadidx].done=1; }
int main(void) { size_t n, m; usCount start, end; size_t roundings[16]; printf("N1527lib test program\n" "-=-=-=-=-=-=-=-=-=-=-\n"); n=mpool_minimum_roundings(roundings, 16); assert(n<16); printf("Minimum roundings from available allocators:\n"); for(m=0; m<n; m++) { printf(" %u\n", roundings[m]); } { mpool pool128, pool4096, poolA; void *temp1, *temp2; size_t usagecount, *alignments, *roundings; pool128=mpool_obtain(alignment128_attributes); temp1=mpool_malloc(pool128, 1); temp2=mpool_malloc(pool128, 1); printf("128 aligned %p (%u), %p (%u)", temp1, mpool_usable_size(pool128, temp1), temp2, mpool_usable_size(pool128, temp2)); assert(!((size_t)temp1 & 127)); assert(!((size_t)temp2 & 127)); mpool_info(pool128, &usagecount, &alignments, &roundings, NULL); printf(" usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]); pool4096=mpool_obtain(alignment4096_attributes); temp1=mpool_malloc(pool4096, 1); temp2=mpool_malloc(pool4096, 1); printf("4096 aligned %p (%u), %p (%u)", temp1, mpool_usable_size(pool4096, temp1), temp2, mpool_usable_size(pool4096, temp2)); assert(!((size_t)temp1 & 4095)); assert(!((size_t)temp2 & 4095)); mpool_info(pool4096, &usagecount, &alignments, &roundings, NULL); printf(" usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]); poolA=mpool_obtain(alignment128_attributes_a); mpool_info(poolA, &usagecount, &alignments, &roundings, NULL); printf("PoolA: usagecount=%u, roundings[0]=%u\n", usagecount, roundings[0]); assert(poolA==pool128); } syspool=mpool_obtain(MPOOL_DEFAULT); srand(1); for(n=0; n<RECORDS; n++) sizes[n]=rand() & 1023; if(1) { unsigned frees=0; printf("Fragmenting free space ...\n"); start=GetUsCount(); while(GetUsCount()-start<3000000000000) { n=rand() % RECORDS; if(ptrs[n]) { mpool_free(syspool, ptrs[n]); ptrs[n]=0; frees++; } else ptrs[n]=mpool_malloc(syspool, sizes[n]); } memset(ptrs, 0, RECORDS*sizeof(void *)); printf("Did %u frees\n", frees); } if(0) { typedef void* mspace; extern mspace get_dlmalloc_mspace(mpool pool); extern void* mspace_malloc(mspace msp, size_t bytes); extern void mspace_free(mspace msp, void* mem); printf("\ndlmalloc Speed test\n" "-------------------\n"); { mspace ms=get_dlmalloc_mspace(syspool); for(m=0; m<3; m++) { size_t count=RECORDS, size=1024; for(n=0; n<RECORDS; n++) sizes[n]=rand() & 1023; start=GetUsCount(); for(n=0; n<RECORDS; n++) { ptrs[n]=mspace_malloc(ms, sizes[n]); } end=GetUsCount(); printf("mspace_malloc() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0)); start=GetUsCount(); for(n=0; n<RECORDS; n++) { mspace_free(ms, ptrs[n]); ptrs[n]=0; } end=GetUsCount(); printf("mspace_free() does %f frees/sec\n\n", RECORDS/((end-start)/1000000000000.0)); } } } if(1) { printf("\nMPool Speed test\n" "----------------\n"); for(m=0; m<3; m++) { size_t count=RECORDS, size=1024; for(n=0; n<RECORDS; n++) sizes[n]=rand() & 1023; start=GetUsCount(); mpool_batch(syspool, NULL, ptrs, sizes, &count, 0); end=GetUsCount(); printf("mpool_batch() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0)); count=RECORDS; start=GetUsCount(); mpool_batch(syspool, NULL, ptrs, NULL, &count, 0); end=GetUsCount(); printf("mpool_batch() does %f frees/sec\n", RECORDS/((end-start)/1000000000000.0)); start=GetUsCount(); for(n=0; n<RECORDS; n++) { ptrs[n]=mpool_malloc(syspool, sizes[n]); } end=GetUsCount(); printf("mpool_malloc() does %f mallocs/sec\n", RECORDS/((end-start)/1000000000000.0)); start=GetUsCount(); for(n=0; n<RECORDS; n++) { mpool_free(syspool, ptrs[n]); ptrs[n]=0; } end=GetUsCount(); printf("mpool_free() does %f frees/sec\n\n", RECORDS/((end-start)/1000000000000.0)); } } #ifdef _MSC_VER printf("Press Return to exit ...\n"); getchar(); #endif return 0; }