File: malloc_bench.c

package info (click to toggle)
emscripten 3.1.69%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 121,872 kB
  • sloc: ansic: 636,110; cpp: 425,974; javascript: 78,401; python: 58,404; sh: 49,154; pascal: 5,237; makefile: 3,365; asm: 2,415; lisp: 1,869
file content (153 lines) | stat: -rw-r--r-- 4,660 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2018 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

// Used internally to test performance of emmalloc against other
// malloc implementations.  (Not run as part of the emscripten test suite).

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // for sbrk()

const int BINS = 32768;
const int BIN_MASK = BINS - 1;
const int ITERS = 6 * 1024 * 1024;
//  12, 64: emmalloc slower
//  12, 28: emmalloc much sbrkier and also slower
// 256, 512: emmalloc faster without USE_MEMORY
const int MIN_SIZE = 16;
const int MAX_SIZE = 64;
const int SIZE_MASK = 7;
const bool POLL_SBRK = false;
const bool USE_REALLOC_UP = true;
const bool USE_REALLOC_DOWN = true;
const bool USE_CALLOC = false;
const bool USE_MEMORY = true;
const bool USE_SHIFTS = false;

void randoms() {
  srandom(1);
  size_t before = (size_t)sbrk(0);
  double sum_sbrk = 0;
  size_t max_sbrk = before;
  void* bins[BINS];
  size_t allocated[BINS];
  size_t total_allocated = 0;
  size_t max_allocated = 0;
  size_t checksum = 0;
  size_t sizes = 0;
  size_t allocations = 0;
  for (int i = 0; i < BINS; i++) {
    bins[i] = NULL;
  }
  for (int i = 0; i < ITERS; i++) {
    int bin = random() & BIN_MASK;
    unsigned int r = random();
    int alloc = r & 1;
    r >>= 1;
    int calloc_ = r & 1;
    r >>= 1;
    unsigned int size = r & 65535;
    r >>= 16;
    int useShifts = r & 1;
    r >>= 1;
    unsigned int shifts = r & 15;
    r >>= 4;
    if (MAX_SIZE) {
      size = size % (MAX_SIZE + 1);
    }
    if (USE_SHIFTS && useShifts) {
      size >>= shifts; // spread out values logarithmically
    }
    if (SIZE_MASK) size = size & ~SIZE_MASK;
    if (MIN_SIZE && size < MIN_SIZE) size = MIN_SIZE;
    if (MAX_SIZE && size > MAX_SIZE) size = MAX_SIZE;
    //printf("%d\n", size);
    if (alloc || !bins[bin]) {
      if (bins[bin]) {
        bool up = size >= allocated[bin];
        if ((up && USE_REALLOC_UP) || (!up && USE_REALLOC_DOWN)) {
          total_allocated -= allocated[bin];
          bins[bin] = realloc(bins[bin], size);
          allocated[bin] = size;
          total_allocated += size;
        } else {
          // malloc and free manually
          free(bins[bin]);
          bins[bin] = NULL;
          total_allocated -= allocated[bin];
          allocated[bin] = 0;
          bins[bin] = malloc(size);
          allocated[bin] = size;
          total_allocated += size;
        }
      } else {
        if (calloc_ && USE_CALLOC) {
          bins[bin] = calloc(size, 1);
          allocated[bin] = size;
          total_allocated += size;
        } else {
          bins[bin] = malloc(size);
          allocated[bin] = size;
          total_allocated += size;
        }
      }
      if (bins[bin]) {
        allocations++;
        sizes += size;
      }
      if (USE_MEMORY && bins[bin]) {
        for (int i = 0; i < size; i++) {
          ((char*)(bins[bin]))[i] = i;
        }
      }
    } else {
      if (USE_MEMORY && bins[bin]) {
        for (int i = 0; i < size; i++) {
          checksum += ((char*)(bins[bin]))[i];
        }
      }
      free(bins[bin]);
      bins[bin] = NULL;
      total_allocated -= allocated[bin];
      allocated[bin] = 0;
    }
    if (total_allocated > max_allocated) {
      max_allocated = total_allocated;
    }
    if (POLL_SBRK) {
      size_t curr = (size_t)sbrk(0);
      if (curr > max_sbrk) max_sbrk = curr;
      sum_sbrk += curr;
    }
  }
  for (int i = 0; i < BINS; i++) {
    if (bins[i]) {
      free(bins[i]);
      total_allocated -= allocated[i];
    }
  }
  size_t after = (size_t)sbrk(0);
  printf("checksum:         %zx\n", checksum);
  printf("allocations:      %zu\n", allocations);
  printf("mean alloc size:  %.2f\n", ((double)sizes) / allocations);
  printf("max allocated:    %zu\n", max_allocated);
  double allocs_at_max = max_allocated / (((double)sizes) / allocations);
  printf("allocations #max  %.2f\n", allocs_at_max);
  size_t sbrk_change = after - before;
  printf("sbrk chng:        %zu\n", sbrk_change);
  printf("sbrk chng/allocs: %.2f\n", sbrk_change / ((double)allocs_at_max));
  printf("overhead:         %.2f\n", -((((double)sizes) / allocations) - (sbrk_change / ((double)allocs_at_max))));
  printf("sbrk top now:     %p\n", (void*)sbrk(0));
  if (POLL_SBRK) {
    printf("sbrk mean change: %.2f\n", (sum_sbrk / (double)ITERS) - before);
    printf("sbrk max change:  %lu\n", max_sbrk - before);
  }
}

int main() {
  randoms();
}