usermode/library/malloc-original/src/malloc-test.c

00001 /* malloc-test.c
00002  * by Wolfram Gloger 1995, 1996
00003  *
00004  * This program is provided `as is', there is no warranty.
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 /* minimal testing */
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 /* All probabilities are parts in 1024. */
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 /* constants for portable */
00079 #define IA                      1366l   /* random number generator */
00080 #define IC                      150889l /* (see Numerical Recipes p. 211) */
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                 /* Try the complete initial word. */
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                         /* small value near power of two */
00169                         r = (1L << (r1 >> 6)) + r2;
00170                 } else if(r1 < 512+20) {
00171                         /* value near a multiple of the page size */
00172                         r = (RANDOM(max_pages)+1)*PAGE_SIZE + r2 - 16;
00173                         /*printf("r = %4lx\n", r);*/
00174                 } else r = RANDOM(max) + 1;
00175         } else r = RANDOM(max) + 1;
00176         /*if(r <= 0) exit(-1);*/
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                         /* SunOS4 does not realloc() a NULL pointer */
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                 /*printf("realloc %d\n", (int)m->size);*/
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 { /* normal malloc call */
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                 /*printf("base_ptr = %lx\n", (long)base_ptr);*/
00342         }
00343         /* attempt to fill up the region below the initial brk */
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                         /* throw in an explicit sbrk call */
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) { /* gather statistics */
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         /* Correct sbrk values. */
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                    /* (1.0 - (double)total_size_max/sbrk_max)*100.0, */
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  * Local variables:
00452  * tab-width:4
00453  * compile-command: "gcc -Wall malloc-test.c -o malloc-test"
00454  * End:
00455  */
00456 

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7