00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <stddef.h>
00004 #include <string.h>
00005 #include <ctype.h>
00006 #include <time.h>
00007
00008 #ifdef __WIN32__
00009 #include <conio.h>
00010 #include <crtdbg.h>
00011 #include <process.h>
00012 #include <windows.h>
00013 #else
00014 typedef void * LPVOID;
00015 typedef long long LONGLONG;
00016 typedef long DWORD;
00017 typedef long LONG;
00018 typedef union _LARGE_INTEGER {
00019 struct {
00020 DWORD LowPart;
00021 LONG HighPart;
00022 };
00023 LONGLONG QuadPart;
00024 } LARGE_INTEGER;
00025 typedef long long _int64;
00026 enum { TRUE = 1, FALSE = 0 };
00027 #include <assert.h>
00028 #define _ASSERTE(x) assert(x)
00029 #define pt_malloc_init(x)
00030 void * pt_malloc (int x)
00031 {
00032 return malloc(x);
00033 }
00034
00035 #define pt_free(x) free(x)
00036 void Sleep (long x)
00037 {
00038 printf ("sleeping for %d seconds.\n", x/1000);
00039 sleep(x/1000);
00040 }
00041
00042 #define QueryPerformanceCounter(x) times(0)
00043 #define QueryPerformanceFrequency(x) CLK_TCK
00044
00045 #define _REENTRANT 1
00046 #include <pthread.h>
00047 typedef void * VoidFunction (void *);
00048 void _beginthread (VoidFunction x, int y, void * z)
00049 {
00050 pthread_t pt;
00051 printf ("creating a thread.\n");
00052 pthread_create(&pt, NULL, x, z);
00053 }
00054 #endif
00055
00056 #include "perfcounters.h"
00057
00058
00059
00060
00061
00062
00063 #define MAX_THREADS 100
00064 #define MAX_BLOCKS 1000000
00065 #define MAX_IIV 1
00066
00067 #define TC_CONTINUE 0
00068 #define TC_PAUSE 1
00069 #define TC_TERMINATE 2
00070
00071 struct lran2_st {
00072 long x, y, v[97];
00073 };
00074
00075 typedef struct thr_data {
00076
00077 int threadno ;
00078 int NumBlocks ;
00079 int seed ;
00080
00081 int min_size ;
00082 int max_size ;
00083
00084 LPVOID *array ;
00085 int asize ;
00086
00087 int cAllocs ;
00088 int cFrees ;
00089 int cThreads ;
00090
00091 PerfCounters cntrs ;
00092
00093 int waitflag ;
00094 int finished ;
00095 struct lran2_st rgen ;
00096
00097 } thread_data;
00098
00099
00100 static void warmup(LPVOID *blkp, int num_chunks, thread_data *pdea );
00101 static void * exercise_heap( void *pinput) ;
00102 static void lran2_init(struct lran2_st* d, long seed) ;
00103 static long lran2(struct lran2_st* d) ;
00104
00105 LPVOID blkp[MAX_BLOCKS] ;
00106 long seqlock=0 ;
00107 int min_size, max_size ;
00108 struct lran2_st rgen ;
00109
00110 extern int cAllocedChunks ;
00111 extern int cAllocedSpace ;
00112 extern int cUsedSpace ;
00113 extern int cFreeChunks ;
00114 extern int cFreeSpace ;
00115
00116 int main()
00117 {
00118 thread_data de_area[MAX_THREADS] ;
00119 thread_data *pdea;
00120 int min_threads, max_threads ;
00121 int num_threads, prevthreads ;
00122 unsigned seed=12345 ;
00123 int sum_allocs ;
00124 int sum_frees ;
00125 double duration ;
00126 char *allocator ;
00127 int ii, i ;
00128
00129 LPVOID tmp ;
00130 int cblks=0 ;
00131 int victim ;
00132 long blk_size ;
00133 int nperthread ;
00134 int chperthread ;
00135 int num_chunks;
00136 int num_rounds ;
00137 int sum_threads ;
00138
00139 LARGE_INTEGER ticks_per_sec ;
00140 LARGE_INTEGER start_cnt, end_cnt ;
00141 _int64 ticks ;
00142 double rate_1=0, rate_n ;
00143 double eused_space ;
00144
00145
00146
00147 printf( "\nTest driver for memory allocators \n") ;
00148 # ifdef WIN32_CRITICAL_SECTIONS
00149 allocator = "PT_MALLOC with WIN32 critical sections" ;
00150 # else
00151 allocator = "PT_MALLOC with spin locks" ;
00152 # endif
00153
00154 printf("Using %s,\n\n", allocator ) ;
00155 printf("chunk size (min,max): ") ;
00156 scanf("%d %d", &min_size, &max_size ) ;
00157 printf("threads (min, max): ") ;
00158 scanf("%d %d", &min_threads, &max_threads) ;
00159 printf("chunks/thread: ") ; scanf("%d", &chperthread ) ;
00160 printf("no of rounds: ") ; scanf("%d", &num_rounds ) ;
00161 printf("random seed: ") ; scanf("%d", &seed) ;
00162
00163 num_chunks = max_threads*chperthread ;
00164 if( num_chunks > MAX_BLOCKS ){
00165 printf("Max %d chunks - exiting\n", MAX_BLOCKS ) ;
00166 return(1) ;
00167 }
00168
00169 lran2_init(&rgen, seed) ;
00170 pt_malloc_init(void) ;
00171
00172 QueryPerformanceFrequency( &ticks_per_sec ) ;
00173
00174 pdea = &de_area[0] ;
00175 memset(&de_area[0], 0, sizeof(thread_data)) ;
00176
00177 prevthreads = 0 ;
00178
00179 for(num_threads=min_threads; num_threads <= max_threads; num_threads++ )
00180 {
00181
00182 nperthread = chperthread ;
00183 warmup(&blkp[prevthreads*chperthread], (num_threads-prevthreads)*chperthread, pdea );
00184
00185 for(i=0; i< num_threads; i++){
00186 de_area[i].threadno = i+1 ;
00187 de_area[i].NumBlocks = num_rounds*nperthread;
00188 de_area[i].array = &blkp[i*nperthread] ;
00189 de_area[i].asize = nperthread ;
00190 de_area[i].min_size = min_size ;
00191 de_area[i].max_size = max_size ;
00192 de_area[i].seed = lran2(&rgen) ; ;
00193 de_area[i].finished = 0 ;
00194 de_area[i].cAllocs = 0 ;
00195 de_area[i].cFrees = 0 ;
00196 de_area[i].cThreads = 0 ;
00197 de_area[i].waitflag = TC_CONTINUE ;
00198 de_area[i].finished = FALSE ;
00199 memset(&de_area[i].cntrs, 0, sizeof(PerfCounters)) ;
00200 lran2_init(&de_area[i].rgen, de_area[i].seed) ;
00201
00202 _beginthread(exercise_heap, 0, &de_area[i]) ;
00203 }
00204
00205 for(ii=0; ii<MAX_IIV ; ii++) {
00206 QueryPerformanceCounter( &start_cnt) ;
00207
00208 Sleep(30000L) ;
00209 printf ("TIME TO DIE!\n");
00210
00211 for(i=0; i< num_threads; i++) de_area[i].waitflag = TC_PAUSE ;
00212
00213 for(i=0; i< num_threads; i++){
00214 while( !de_area[i].finished ){
00215
00216 }
00217 }
00218
00219 QueryPerformanceCounter( &end_cnt) ;
00220
00221 sum_frees = sum_allocs =0 ;
00222 sum_threads = 0 ;
00223 for(i=0;i< num_threads; i++){
00224 sum_allocs += de_area[i].cAllocs ;
00225 sum_frees += de_area[i].cFrees ;
00226 sum_threads += de_area[i].cThreads ;
00227 de_area[i].cAllocs = de_area[i].cFrees = 0;
00228 }
00229 ticks = end_cnt.QuadPart - start_cnt.QuadPart ;
00230 duration = (double)ticks/ticks_per_sec.QuadPart ;
00231
00232 rate_n = sum_allocs/duration ;
00233 if( rate_1 == 0){
00234 rate_1 = rate_n ;
00235 }
00236
00237
00238 eused_space = (0.5*(min_size+max_size)*num_threads*chperthread) ;
00239
00240 #if 0
00241 cur_mallinfo = pt_mallinfo() ;
00242 #endif
00243 printf("%2d ", num_threads ) ;
00244 printf("%2d ", ii ) ;
00245 printf("%6.3f", duration ) ;
00246 printf("%6.3f", rate_n/rate_1 ) ;
00247 printf("%8.0f", sum_allocs/duration ) ;
00248
00249 #if 0
00250 printf(" %6.2f", (100.0*(double)cur_mallinfo.uordblks)/eused_space ) ;
00251 printf(" %6.2f", (100.0*eused_space)/cur_mallinfo.arena ) ;
00252
00253 printf(" %6d", cur_mallinfo.ordblks ) ;
00254 printf(" %10d", cur_mallinfo.arena ) ;
00255 #endif
00256 printf(" %5d", sum_threads ) ;
00257
00258 printf("\n") ;
00259
00260
00261 for(i=0; i< num_threads; i++){
00262 if( ii == MAX_IIV-1 ) de_area[i].waitflag = TC_TERMINATE ;
00263 else de_area[i].waitflag = TC_CONTINUE ;
00264 }
00265
00266 Sleep(5000L) ;
00267 }
00268 prevthreads = num_threads ;
00269
00270 }
00271
00272
00273 #ifdef _DEBUG
00274 _cputs("Hit any key to exit...") ; (void)_getch() ;
00275 #endif
00276
00277 return(0) ;
00278
00279 }
00280
00281
00282
00283
00284 static void * exercise_heap( void *pinput)
00285 {
00286 thread_data *pdea;
00287 int cblks=0 ;
00288 int victim ;
00289 long blk_size ;
00290 int range ;
00291
00292
00293
00294 pdea = (thread_data *)pinput ;
00295 BEGIN:
00296 pdea->finished = FALSE ;
00297 pdea->cThreads++ ;
00298 range = pdea->max_size - pdea->min_size ;
00299
00300
00301 for( cblks=0; cblks<pdea->NumBlocks; cblks++){
00302 victim = lran2(&pdea->rgen)%pdea->asize ;
00303 pt_free(pdea->array[victim]) ;
00304 pdea->cFrees++ ;
00305
00306 blk_size = pdea->min_size+lran2(&pdea->rgen)%range ;
00307 pdea->array[victim] = pt_malloc(blk_size) ;
00308 _ASSERTE(pdea->array[victim] != NULL) ;
00309 pdea->cAllocs++ ;
00310 }
00311
00312 pdea->finished = TRUE ;
00313 while( pdea->waitflag == TC_PAUSE){
00314 Sleep(0) ;
00315 }
00316 if( pdea->waitflag == TC_CONTINUE){
00317 _beginthread(exercise_heap, 0, pdea) ;
00318 }
00319
00320
00321 printf("Thread %u terminating: %d allocs, %d frees\n",
00322 pdea->threadno, pdea->cAllocs, pdea->cFrees) ;
00323
00324 return (void *) 0;
00325
00326 }
00327
00328 static void warmup(LPVOID *blkp, int num_chunks, thread_data *pdea )
00329 {
00330 int cblks ;
00331 int victim ;
00332 int blk_size ;
00333 LPVOID tmp ;
00334
00335
00336 for( cblks=0; cblks<num_chunks; cblks++){
00337 blk_size = min_size+lran2(&rgen)%(max_size-min_size) ;
00338 blkp[cblks] = pt_malloc(blk_size) ;
00339 _ASSERTE(blkp[cblks] != NULL) ;
00340 }
00341
00342
00343 for( cblks=num_chunks; cblks > 0 ; cblks--){
00344 victim = lran2(&rgen)%cblks ;
00345 tmp = blkp[victim] ;
00346 blkp[victim] = blkp[cblks-1] ;
00347 blkp[cblks-1] = tmp ;
00348 }
00349
00350 for( cblks=0; cblks<4*num_chunks; cblks++){
00351 victim = lran2(&rgen)%num_chunks ;
00352 pt_free(blkp[victim]) ;
00353
00354 blk_size = min_size+lran2(&rgen)%(max_size - min_size) ;
00355 blkp[victim] = pt_malloc(blk_size) ;
00356 _ASSERTE(blkp[victim] != NULL) ;
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 #ifndef _LRAN2_H
00369 #define _LRAN2_H
00370
00371 #define LRAN2_MAX 714025l
00372 #define IA 1366l
00373 #define IC 150889l
00374
00375
00376
00377
00378
00379 static void
00380 lran2_init(struct lran2_st* d, long seed)
00381 {
00382 long x;
00383 int j;
00384
00385 x = (IC - seed) % LRAN2_MAX;
00386 if(x < 0) x = -x;
00387 for(j=0; j<97; j++) {
00388 x = (IA*x + IC) % LRAN2_MAX;
00389 d->v[j] = x;
00390 }
00391 d->x = (IA*x + IC) % LRAN2_MAX;
00392 d->y = d->x;
00393 }
00394
00395
00396 static long
00397 lran2(struct lran2_st* d)
00398 {
00399 int j = (d->y % 97);
00400
00401 d->y = d->v[j];
00402 d->x = (IA*d->x + IC) % LRAN2_MAX;
00403 d->v[j] = d->x;
00404 return d->y;
00405 }
00406
00407 #undef IA
00408 #undef IC
00409
00410 #endif
00411
00412