diff options
Diffstat (limited to '')
| -rw-r--r-- | drivers/nedmalloc/test.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/drivers/nedmalloc/test.c b/drivers/nedmalloc/test.c new file mode 100644 index 000000000..8b9fed81d --- /dev/null +++ b/drivers/nedmalloc/test.c @@ -0,0 +1,356 @@ +/* test.c
+An example of how to use nedalloc
+(C) 2005-2007 Niall Douglas
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "nedmalloc.c"
+
+#define THREADS 5
+#define RECORDS (100000/THREADS)
+#define TORTURETEST 1
+
+static int whichmalloc;
+static int doRealloc;
+static struct threadstuff_t
+{
+ int ops;
+ unsigned int *toalloc;
+ void **allocs;
+ char cachesync1[128];
+ int done;
+ char cachesync2[128];
+} threadstuff[THREADS];
+
+static void threadcode(int);
+
+#ifdef WIN32
+static DWORD WINAPI _threadcode(LPVOID a)
+{
+ threadcode((int)(size_t) a);
+ return 0;
+}
+#define THREADVAR HANDLE
+#define THREADINIT(v, id) (*v=CreateThread(NULL, 0, _threadcode, (LPVOID)(size_t) id, 0, NULL))
+#define THREADSLEEP(v) SleepEx(v, FALSE)
+#define THREADWAIT(v) (WaitForSingleObject(v, INFINITE), 0)
+
+typedef unsigned __int64 usCount;
+static FORCEINLINE 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);
+}
+
+static HANDLE win32heap;
+static void *win32malloc(size_t size)
+{
+ return HeapAlloc(win32heap, 0, size);
+}
+static void *win32realloc(void *p, size_t size)
+{
+ return HeapReAlloc(win32heap, 0, p, size);
+}
+static void win32free(void *mem)
+{
+ HeapFree(win32heap, 0, mem);
+}
+
+static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc, win32malloc };
+static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc, win32realloc };
+static void (*const frees[])(void *mem)={ free, nedfree, win32free };
+#else
+static void *_threadcode(void *a)
+{
+ threadcode((int)(size_t) a);
+ return 0;
+}
+#define THREADVAR pthread_t
+#define THREADINIT(v, id) pthread_create(v, NULL, _threadcode, (void *)(size_t) id)
+#define THREADSLEEP(v) usleep(v*1000)
+#define THREADWAIT(v) pthread_join(v, NULL)
+
+typedef unsigned long long usCount;
+static FORCEINLINE usCount GetUsCount()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return ((usCount) tv.tv_sec*1000000000000LL)+tv.tv_usec*1000000LL;
+}
+
+static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc };
+static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc };
+static void (*const frees[])(void *mem)={ free, nedfree };
+#endif
+static usCount times[THREADS];
+
+
+static FORCEINLINE unsigned int myrandom(unsigned int *seed)
+{
+ *seed=1664525UL*(*seed)+1013904223UL;
+ return *seed;
+}
+
+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;
+}
+
+static double runtest()
+{
+ unsigned int seed=1;
+ int n, i;
+ double opspersec=0;
+ THREADVAR threads[THREADS];
+ for(n=0; n<THREADS; n++)
+ {
+ unsigned int *toallocptr;
+ int m;
+ threadstuff[n].ops=0;
+ times[n]=0;
+ threadstuff[n].toalloc=toallocptr=calloc(RECORDS, sizeof(unsigned int));
+ threadstuff[n].allocs=calloc(RECORDS, sizeof(void *));
+ for(m=0; m<RECORDS; m++)
+ {
+ unsigned int size=myrandom(&seed);
+ if(size<(1<<30))
+ { /* Make it two power multiple of less than 512 bytes to
+ model frequent C++ new's */
+ size=4<<(size & 7);
+ }
+ else
+ {
+ size&=0x3FFF; /* < 16Kb */
+ /*size&=0x1FFF;*/ /* < 8Kb */
+ /*size=(1<<6)<<(size & 7);*/ /* < 8Kb */
+ }
+ *toallocptr++=size;
+ }
+ }
+#ifdef TORTURETEST
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(i=0; i<32; i++)
+ {
+ int found=-1;
+ do
+ {
+ for(n=0; n<THREADS; n++)
+ {
+ THREADSLEEP(100);
+ if(threadstuff[n].done)
+ {
+ found=n;
+ break;
+ }
+ }
+ } while(found<0);
+ THREADWAIT(threads[found]);
+ threads[found]=0;
+ THREADINIT(&threads[found], found);
+ printf("Relaunched thread %d\n", found);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#else
+#if 1
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#else
+ /* Quick realloc() test */
+ doRealloc=1;
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#endif
+#endif
+ {
+ usCount totaltime=0;
+ int totalops=0;
+ for(n=0; n<THREADS; n++)
+ {
+ totaltime+=times[n];
+ totalops+=threadstuff[n].ops;
+ }
+ opspersec=1000000000000.0*totalops/totaltime*THREADS;
+ printf("This allocator achieves %lfops/sec under %d threads\n", opspersec, THREADS);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ free(threadstuff[n].allocs); threadstuff[n].allocs=0;
+ free(threadstuff[n].toalloc); threadstuff[n].toalloc=0;
+ }
+ return opspersec;
+}
+
+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;
+}
|
