00001
00002
00003
00004
00005
00006
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <unistd.h>
00010 #include <sys/types.h>
00011 #include <sys/time.h>
00012 #include <sys/resource.h>
00013 #include <malloc.h>
00014
00015 #ifndef MEMORY
00016 #define MEMORY 4000000l
00017 #endif
00018 #ifndef BINS_MAX
00019 #define BINS_MAX 32768
00020 #endif
00021 #define SBINS_MAX 1024
00022 #define SIZE 10000
00023 #define I_MAX 5000
00024 #ifndef I_AVERAGE
00025 #define I_AVERAGE 200
00026 #endif
00027 #define ACTIONS_MAX 50
00028 #ifndef SBRK_AVG
00029 #define SBRK_AVG 0
00030 #endif
00031 #ifndef MMAP_THRESH
00032 #define MMAP_THRESH 0
00033 #endif
00034 #ifndef TEST
00035 #define TEST 4
00036 #endif
00037 #ifndef TEST_INC
00038 #define TEST_INC 2047
00039 #endif
00040 #if defined(__i386__) || defined(__sparc__) || defined(mips)
00041 #define PAGE_SIZE 4096
00042 #elif defined(__alpha__)
00043 #define PAGE_SIZE 8192
00044 #elif defined(__SVR4)
00045 #define PAGE_SIZE 8192
00046 #else
00047 #error "Define PAGE_SIZE !"
00048 #endif
00049 #define RANDOM(s) (lran2(0) % (s))
00050
00051
00052 #ifndef PROB_MEMALIGN
00053 #define PROB_MEMALIGN 3
00054 #endif
00055 #ifndef PROB_REALLOC
00056 #define PROB_REALLOC 70
00057 #endif
00058 #ifndef PROB_CALLOC
00059 #define PROB_CALLOC 30
00060 #endif
00061
00062 struct bin {
00063 unsigned char *ptr;
00064 unsigned long size;
00065 } m[BINS_MAX], sm[SBINS_MAX];
00066
00067 unsigned long size = SIZE, bins=0, sbins=0;
00068 unsigned long total_size=0, total_size_max=0;
00069 unsigned char *base_ptr;
00070 unsigned long base_save;
00071
00072 long
00073 #if __STDC__
00074 lran2(long seed)
00075 #else
00076 lran2(seed) long seed;
00077 #endif
00078 #define LRAN2_MAX 714025l
00079 #define IA 1366l
00080 #define IC 150889l
00081 {
00082 static int first = 1;
00083 static long x, y, v[97];
00084 int j;
00085
00086 if(seed || first) {
00087 first = 0;
00088 x = (IC - seed) % LRAN2_MAX;
00089 if(x < 0) x = -x;
00090 for(j=0; j<97; j++) {
00091 x = (IA*x + IC) % LRAN2_MAX;
00092 v[j] = x;
00093 }
00094 x = (IA*x + IC) % LRAN2_MAX;
00095 y = x;
00096 }
00097 j = y % 97;
00098 y = v[j];
00099 x = (IA*x + IC) % LRAN2_MAX;
00100 v[j] = x;
00101 return y;
00102 }
00103 #undef IA
00104 #undef IC
00105
00106 void
00107 #if __STDC__
00108 mem_init(unsigned char *ptr, unsigned long size)
00109 #else
00110 mem_init(ptr, size) unsigned char *ptr; unsigned long size;
00111 #endif
00112 {
00113 unsigned long i, j;
00114
00115 if(size == 0) return;
00116 if(size > sizeof(unsigned long)) {
00117
00118 *(unsigned long *)ptr = (unsigned long)ptr ^ size;
00119 i = TEST_INC;
00120 } else
00121 i = 0;
00122 for(; i<size; i+=TEST_INC) {
00123 j = (unsigned long)ptr ^ i;
00124 ptr[i] = ((j ^ (j>>8)) & 0xFF);
00125 }
00126 j = (unsigned long)ptr ^ (size-1);
00127 ptr[size-1] = ((j ^ (j>>8)) & 0xFF);
00128 }
00129
00130 int
00131 #if __STDC__
00132 mem_check(unsigned char *ptr, unsigned long size)
00133 #else
00134 mem_check(ptr, size) unsigned char *ptr; unsigned long size;
00135 #endif
00136 {
00137 unsigned long i, j;
00138
00139 if(size == 0) return 0;
00140 if(size > sizeof(unsigned long)) {
00141 if(*(unsigned long *)ptr != ((unsigned long)ptr ^ size)) return 1;
00142 i = TEST_INC;
00143 } else
00144 i = 0;
00145 for(; i<size; i+=TEST_INC) {
00146 j = (unsigned long)ptr ^ i;
00147 if(ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 2;
00148 }
00149 j = (unsigned long)ptr ^ (size-1);
00150 if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 3;
00151 return 0;
00152 }
00153
00154 long
00155 #if __STDC__
00156 random_size(long max)
00157 #else
00158 random_size(max) long max;
00159 #endif
00160 {
00161 long r1, r2, r, max_pages;
00162
00163 max_pages = max/PAGE_SIZE;
00164 if(max_pages > 0) {
00165 r1 = RANDOM(1024);
00166 r2 = (r1 & 7)*4;
00167 if(r1 < 512) {
00168
00169 r = (1L << (r1 >> 6)) + r2;
00170 } else if(r1 < 512+20) {
00171
00172 r = (RANDOM(max_pages)+1)*PAGE_SIZE + r2 - 16;
00173
00174 } else r = RANDOM(max) + 1;
00175 } else r = RANDOM(max) + 1;
00176
00177 return r;
00178 }
00179
00180 void
00181 #if __STDC__
00182 bin_alloc(struct bin *m)
00183 #else
00184 bin_alloc(m) struct bin *m;
00185 #endif
00186 {
00187 long r, key;
00188 unsigned long sz;
00189
00190 #if TEST > 0
00191 if(mem_check(m->ptr, m->size)) {
00192 printf("memory corrupt at %p, size=%lu!\n", m->ptr, m->size);
00193 exit(1);
00194 }
00195 #endif
00196 total_size -= m->size;
00197 r = RANDOM(1024);
00198 if(r < PROB_MEMALIGN) {
00199 if(m->size > 0) free(m->ptr);
00200 m->size = random_size(size);
00201 m->ptr = (unsigned char *)memalign(4 << RANDOM(8), m->size);
00202 } else if(r < (PROB_MEMALIGN + PROB_REALLOC)) {
00203 if(m->size == 0) {
00204 #ifndef __sparc__
00205 m->ptr = NULL;
00206 #else
00207
00208 m->ptr = (unsigned char *)malloc(1);
00209 #endif
00210 }
00211 #if TEST > 2
00212 key = RANDOM(256);
00213 sz = m->size;
00214 for(r=0; r<sz; r++) m->ptr[r] = (r ^ key) & 0xFF;
00215 #endif
00216 m->size = random_size(size);
00217
00218 m->ptr = (unsigned char *)realloc(m->ptr, m->size);
00219 #if TEST > 2
00220 if(m->size < sz) sz = m->size;
00221 for(r=0; r<sz; r++)
00222 if(m->ptr[r] != ((r ^ key) & 0xFF)) {
00223 printf("realloc bug !\n");
00224 exit(1);
00225 }
00226 #endif
00227 } else if(r < (PROB_MEMALIGN + PROB_REALLOC + PROB_CALLOC)) {
00228 if(m->size > 0) free(m->ptr);
00229 m->size = random_size(size);
00230 m->ptr = (unsigned char *)calloc(m->size, 1);
00231 #if TEST > 2
00232 for(r=0; r<m->size; r++)
00233 if(m->ptr[r] != '\0') {
00234 printf("calloc bug !\n");
00235 exit(1);
00236 }
00237 #endif
00238 } else {
00239 if(m->size > 0) free(m->ptr);
00240 m->size = random_size(size);
00241 m->ptr = (unsigned char *)malloc(m->size);
00242 }
00243 if(!m->ptr) {
00244 printf("out of memory!\n");
00245 exit(1);
00246 }
00247 total_size += m->size;
00248 if(total_size > total_size_max) total_size_max = total_size;
00249 #if TEST > 0
00250 mem_init(m->ptr, m->size);
00251 #endif
00252 if(m->ptr < base_ptr) {
00253 #ifdef VERBOSE
00254 printf("hmmm, allocating below brk...\n");
00255 #endif
00256 base_ptr = m->ptr;
00257 }
00258 }
00259
00260 void
00261 #if __STDC__
00262 bin_free(struct bin *m)
00263 #else
00264 bin_free(m) struct bin *m;
00265 #endif
00266 {
00267 if(m->size == 0) return;
00268 #if TEST > 0
00269 if(mem_check(m->ptr, m->size)) {
00270 printf("memory corrupt!\n");
00271 exit(1);
00272 }
00273 #endif
00274 total_size -= m->size;
00275 free(m->ptr);
00276 m->size = 0;
00277 }
00278
00279 void
00280 bin_test()
00281 {
00282 unsigned int b;
00283
00284 for(b=0; b<bins; b++) {
00285 if(mem_check(m[b].ptr, m[b].size)) {
00286 printf("memory corrupt!\n");
00287 exit(1);
00288 }
00289 }
00290 for(b=0; b<sbins; b++) {
00291 if(mem_check(sm[b].ptr, sm[b].size)) {
00292 printf("memory corrupt!\n");
00293 exit(1);
00294 }
00295 }
00296 }
00297
00298 void
00299 print_times()
00300 {
00301 struct rusage ru;
00302 long total_sec, total_usec;
00303
00304 getrusage(RUSAGE_SELF, &ru);
00305 printf(" u=%ld.%06ldsec",
00306 (long)ru.ru_utime.tv_sec, (long)ru.ru_utime.tv_usec);
00307 printf(" s=%ld.%06ldsec",
00308 (long)ru.ru_stime.tv_sec, (long)ru.ru_stime.tv_usec);
00309 total_usec = (long)ru.ru_utime.tv_usec + (long)ru.ru_stime.tv_usec;
00310 total_sec = (long)ru.ru_utime.tv_sec + (long)ru.ru_stime.tv_sec;
00311 if(total_usec >= 1000000) {
00312 total_usec -= 1000000;
00313 total_sec++;
00314 }
00315 printf(" t=%ld.%06ldsec", total_sec, total_usec);
00316 }
00317
00318 int
00319 #if __STDC__
00320 main(int argc, char *argv[])
00321 #else
00322 main(argc, argv) int argc; char *argv[];
00323 #endif
00324 {
00325 int i, j, next_i, count, max=I_MAX, actions;
00326 unsigned int b;
00327 long sbrk_max, sum;
00328 double sbrk_used_sum, total_size_sum;
00329 void* dummy = 0;
00330
00331 if(argc > 1) max = atoi(argv[1]);
00332 if(argc > 2) size = atoi(argv[2]);
00333 lran2((long)max ^ size);
00334 bins = (MEMORY/size)*4;
00335 if(bins > BINS_MAX) bins = BINS_MAX;
00336 base_ptr = (unsigned char *)sbrk(0);
00337 sum = (long)base_ptr % PAGE_SIZE;
00338 if(sum > 0) {
00339 if((char *)sbrk((long)PAGE_SIZE - sum) == (char *)-1) exit(1);
00340 base_ptr += (long)PAGE_SIZE - sum;
00341
00342 }
00343
00344 for(i=0; i<10000; i++) {
00345 dummy = malloc(1);
00346 if(dummy >= (void*)base_ptr) break;
00347 }
00348 free(dummy);
00349 base_save = ((unsigned long)base_ptr >> 24) << 24;
00350 #if MMAP_THRESH > 0
00351 if(!mallopt(-3, MMAP_THRESH)) printf("mallopt failed!\n");
00352 if(!mallopt(-4, 200)) printf("mallopt failed!\n");
00353 #endif
00354 #ifdef VERBOSE
00355 printf("# mmap_thresh=%d\n", MMAP_THRESH);
00356 printf("# bins=%d max=%d size=%d\n", bins, max, size);
00357 printf("# base=%lx\n", base_save);
00358 #endif
00359 for(b=0; b<bins; b++) {
00360 if(RANDOM(2) == 0) bin_alloc(&m[b]);
00361 else m[b].size = 0;
00362 }
00363 sbrk_max = 0;
00364 sbrk_used_sum = total_size_sum = 0.0;
00365 for(i=next_i=count=0; i<=max;) {
00366 #if TEST > 1
00367 bin_test();
00368 #endif
00369 #ifdef MSTATS
00370 malloc_stats();
00371 #endif
00372 actions = RANDOM(ACTIONS_MAX);
00373 for(j=0; j<actions; j++) {
00374 b = RANDOM(bins);
00375 bin_free(&m[b]);
00376 #if TEST > 3
00377 bin_test();
00378 #endif
00379 }
00380 i += actions;
00381 #ifdef AFTER_FREE
00382 AFTER_FREE;
00383 #endif
00384 #if SBRK_AVG > 0
00385 if(sbins<SBINS_MAX && RANDOM(SBRK_AVG)==0) {
00386
00387 sm[sbins].size = RANDOM(10000)+1;
00388 sm[sbins].ptr = sbrk(sm[sbins].size);
00389 if(sbins>0 && sm[sbins].ptr==(sm[sbins-1].ptr+sm[sbins-1].size)) {
00390 sm[sbins-1].size += sm[sbins].size;
00391 sbins--;
00392 }
00393 #ifdef VERBOSE
00394 printf("sbrk #%d %p %ld\n", sbins, sm[sbins].ptr, sm[sbins].size);
00395 #endif
00396 #if TEST > 0
00397 mem_init(sm[sbins].ptr, sm[sbins].size);
00398 #endif
00399 sbins++;
00400 }
00401 #endif
00402 actions = RANDOM(ACTIONS_MAX);
00403 for(j=0; j<actions; j++) {
00404 b = RANDOM(bins);
00405 bin_alloc(&m[b]);
00406 #if TEST > 3
00407 bin_test();
00408 #endif
00409 }
00410 i += actions;
00411 if(i >= next_i) {
00412 count++;
00413 sum = (long)sbrk(0);
00414 if(sum > sbrk_max) sbrk_max = sum;
00415 sbrk_used_sum += sum;
00416 total_size_sum += (double)total_size;
00417 #ifdef VERBOSE
00418 printf("%8d %7lu\n", i, total_size);
00419 #endif
00420 next_i += I_AVERAGE;
00421 }
00422 }
00423
00424
00425 sbrk_max -= (long)base_ptr;
00426 sbrk_used_sum -= (double)count*(long)base_ptr;
00427 #ifdef VERBOSE
00428 printf("# initial brk: %lx\n", (long)base_ptr);
00429 printf("# max. sbrk()'ed memory: %ld bytes\n", sbrk_max);
00430 printf("# avg. sbrk()'ed memory: %ld bytes\n",
00431 (long)(sbrk_used_sum/count));
00432 printf("# current size allocated: %ld bytes\n", total_size);
00433 printf("# maximum size allocated: %ld bytes\n", total_size_max);
00434 printf("# average size allocated: %.1f bytes\n", total_size_sum/count);
00435 printf("# current heap waste: %.2f%%\n",
00436 (1.0 - (double)total_size_max/sbrk_max)*100.0);
00437 printf("# average heap waste: %.2f%%\n",
00438 (1.0 - (double)total_size_sum/sbrk_used_sum)*100.0);
00439 printf("# total sbrk calls performed: %d\n", sbins);
00440 #else
00441 printf("size=%7ld waste=%7.3f%%", size,
00442
00443 (1.0 - (double)total_size_sum/sbrk_used_sum)*100.0);
00444 print_times();
00445 printf("\n");
00446 #endif
00447 return 0;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456