1 // Copyright 2018 The Emscripten Authors.  All rights reserved.
2 // Emscripten is available under two separate licenses, the MIT license and the
3 // University of Illinois/NCSA Open Source License.  Both these licenses can be
4 // found in the LICENSE file.
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h> // for sbrk()
10 
11 const int BINS = 32768;
12 const int BIN_MASK = BINS - 1;
13 const int ITERS = 6 * 1024 * 1024;
14 //  12, 64: emmalloc slower
15 //  12, 28: emmalloc much sbrkier and also slower
16 // 256, 512: emmalloc faster without USE_MEMORY
17 const int MIN_SIZE = 16;
18 const int MAX_SIZE = 64;
19 const int SIZE_MASK = 7;
20 const bool POLL_SBRK = false;
21 const bool USE_REALLOC_UP = true;
22 const bool USE_REALLOC_DOWN = true;
23 const bool USE_CALLOC = false;
24 const bool USE_MEMORY = true;
25 const bool USE_SHIFTS = false;
26 
randoms()27 void randoms() {
28   srandom(1);
29   size_t before = (size_t)sbrk(0);
30   double sum_sbrk = 0;
31   size_t max_sbrk = before;
32   void* bins[BINS];
33   size_t allocated[BINS];
34   size_t total_allocated = 0;
35   size_t max_allocated = 0;
36   size_t checksum = 0;
37   size_t sizes = 0;
38   size_t allocations = 0;
39   for (int i = 0; i < BINS; i++) {
40     bins[i] = NULL;
41   }
42   for (int i = 0; i < ITERS; i++) {
43     int bin = random() & BIN_MASK;
44     unsigned int r = random();
45     int alloc = r & 1;
46     r >>= 1;
47     int calloc_ = r & 1;
48     r >>= 1;
49     unsigned int size = r & 65535;
50     r >>= 16;
51     int useShifts = r & 1;
52     r >>= 1;
53     unsigned int shifts = r & 15;
54     r >>= 4;
55     if (MAX_SIZE) {
56       size = size % (MAX_SIZE + 1);
57     }
58     if (USE_SHIFTS && useShifts) {
59       size >>= shifts; // spread out values logarithmically
60     }
61     if (SIZE_MASK) size = size & ~SIZE_MASK;
62     if (MIN_SIZE && size < MIN_SIZE) size = MIN_SIZE;
63     if (MAX_SIZE && size > MAX_SIZE) size = MAX_SIZE;
64     //printf("%d\n", size);
65     if (alloc || !bins[bin]) {
66       if (bins[bin]) {
67         bool up = size >= allocated[bin];
68         if ((up && USE_REALLOC_UP) || (!up && USE_REALLOC_DOWN)) {
69           total_allocated -= allocated[bin];
70           bins[bin] = realloc(bins[bin], size);
71           allocated[bin] = size;
72           total_allocated += size;
73         } else {
74           // malloc and free manually
75           free(bins[bin]);
76           bins[bin] = NULL;
77           total_allocated -= allocated[bin];
78           allocated[bin] = 0;
79           bins[bin] = malloc(size);
80           allocated[bin] = size;
81           total_allocated += size;
82         }
83       } else {
84         if (calloc_ && USE_CALLOC) {
85           bins[bin] = malloc(size);
86           allocated[bin] = size;
87           total_allocated += size;
88         } else {
89           bins[bin] = calloc(size, 1);
90           allocated[bin] = size;
91           total_allocated += size;
92         }
93       }
94       if (bins[bin]) {
95         allocations++;
96         sizes += size;
97       }
98       if (USE_MEMORY && bins[bin]) {
99         for (int i = 0; i < size; i++) {
100           ((char*)(bins[bin]))[i] = i;
101         }
102       }
103     } else {
104       if (USE_MEMORY && bins[bin]) {
105         for (int i = 0; i < size; i++) {
106           checksum += ((char*)(bins[bin]))[i];
107         }
108       }
109       free(bins[bin]);
110       bins[bin] = NULL;
111       total_allocated -= allocated[bin];
112       allocated[bin] = 0;
113     }
114     if (total_allocated > max_allocated) {
115       max_allocated = total_allocated;
116     }
117     if (POLL_SBRK) {
118       size_t curr = (size_t)sbrk(0);
119       if (curr > max_sbrk) max_sbrk = curr;
120       sum_sbrk += curr;
121     }
122   }
123   for (int i = 0; i < BINS; i++) {
124     if (bins[i]) {
125       free(bins[i]);
126       total_allocated -= allocated[i];
127     }
128   }
129   size_t after = (size_t)sbrk(0);
130   printf("checksum:         %x\n", checksum);
131   printf("allocations:      %d\n", allocations);
132   printf("mean alloc size:  %.2f\n", double(sizes) / allocations);
133   printf("max allocated:    %u\n", max_allocated);
134   double allocs_at_max = max_allocated / (double(sizes) / allocations);
135   printf("allocations #max  %.2f\n", allocs_at_max);
136   size_t sbrk_change = after - before;
137   printf("sbrk chng:        %u\n", sbrk_change);
138   printf("sbrk chng/allocs: %.2f\n", sbrk_change / double(allocs_at_max));
139   printf("overhead:         %.2f\n", -((double(sizes) / allocations) - (sbrk_change / double(allocs_at_max))));
140   printf("sbrk top now:     %p\n", (void*)sbrk(0));
141   if (POLL_SBRK) {
142     printf("sbrk mean change: %.2f\n", (sum_sbrk / double(ITERS)) - before);
143     printf("sbrk max change:  %u\n", max_sbrk - before);
144   }
145 }
146 
main()147 int main() {
148   randoms();
149 }
150 
151