-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.c
More file actions
153 lines (124 loc) · 4.39 KB
/
benchmark.c
File metadata and controls
153 lines (124 loc) · 4.39 KB
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
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// compile two ways:
// gcc -pthread -O2 -DUSE_CUSTOM benchmark.c allocator.c -o bench_custom
// gcc -pthread -O2 benchmark.c -o bench_libc
#ifdef USE_CUSTOM
#include "allocator.h"
#define MALLOC mymalloc
#define FREE myfree
#define REALLOC myrealloc
#define CALLOC mycalloc
#else
#define MALLOC malloc
#define FREE free
#define REALLOC realloc
#define CALLOC calloc
#endif
#define NS(ts) ((ts).tv_sec * 1000000000LL + (ts).tv_nsec)
static double elapsed_ms(struct timespec a, struct timespec b) {
return (NS(b) - NS(a)) / 1e6;
}
// ── Bench 1: single-threaded alloc+free pairs ────────────────────────────────
void bench_single(int iterations) {
struct timespec a, b;
clock_gettime(CLOCK_MONOTONIC, &a);
for (int i = 0; i < iterations; i++) {
void *p = MALLOC((rand() % 512) + 8);
FREE(p);
}
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" single alloc+free (%dk iters): %.2f ms\n", iterations / 1000,
elapsed_ms(a, b));
}
// ── Bench 2: batch alloc then batch free ─────────────────────────────────────
void bench_batch(int n) {
void **ptrs = malloc(n * sizeof(void *)); // always libc for harness
struct timespec a, b;
clock_gettime(CLOCK_MONOTONIC, &a);
for (int i = 0; i < n; i++)
ptrs[i] = MALLOC((rand() % 256) + 8);
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" batch alloc (%dk): %.2f ms\n", n / 1000, elapsed_ms(a, b));
clock_gettime(CLOCK_MONOTONIC, &a);
for (int i = 0; i < n; i++)
FREE(ptrs[i]);
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" batch free (%dk): %.2f ms\n", n / 1000, elapsed_ms(a, b));
free(ptrs);
}
// ── Bench 3: mixed sizes (small + large) ─────────────────────────────────────
void bench_mixed_sizes(int iterations) {
struct timespec a, b;
clock_gettime(CLOCK_MONOTONIC, &a);
for (int i = 0; i < iterations; i++) {
size_t size = (i % 10 == 0) ? 200000 : (rand() % 512) + 8;
void *p = MALLOC(size);
FREE(p);
}
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" mixed sizes (%dk iters): %.2f ms\n", iterations / 1000,
elapsed_ms(a, b));
}
// ── Bench 4: realloc chain ───────────────────────────────────────────────────
void bench_realloc(int iterations) {
struct timespec a, b;
clock_gettime(CLOCK_MONOTONIC, &a);
void *p = MALLOC(8);
for (int i = 0; i < iterations; i++) {
p = REALLOC(p, (i % 512) + 8);
}
FREE(p);
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" realloc chain(%dk iters): %.2f ms\n", iterations / 1000,
elapsed_ms(a, b));
}
// ── Bench 5: multithreaded ───────────────────────────────────────────────────
#define BENCH_THREADS 8
#define BENCH_ITERS 5000
void *thread_bench(void *arg) {
void *ptrs[100];
unsigned int seed = (unsigned int)(size_t)arg; // unique seed per thread
for (int i = 0; i < BENCH_ITERS; i++) {
for (int j = 0; j < 100; j++)
ptrs[j] = MALLOC((rand_r(&seed) % 256) + 8);
for (int j = 0; j < 100; j++)
FREE(ptrs[j]);
}
return NULL;
}
void bench_multithreaded() {
pthread_t threads[BENCH_THREADS];
struct timespec a, b;
clock_gettime(CLOCK_MONOTONIC, &a);
for (int i = 0; i < BENCH_THREADS; i++)
pthread_create(&threads[i], NULL, thread_bench, (void *)(size_t)(i + 1));
for (int i = 0; i < BENCH_THREADS; i++)
pthread_join(threads[i], NULL);
clock_gettime(CLOCK_MONOTONIC, &b);
printf(" multithreaded(%d threads, %dk iters each): %.2f ms\n",
BENCH_THREADS, BENCH_ITERS / 1000, elapsed_ms(a, b));
}
int main() {
#ifdef USE_CUSTOM
printf("=== custom allocator ===\n");
#else
printf("=== libc allocator ===\n");
#endif
srand(42); // same seed for fair comparison
printf("\n-- single threaded --\n");
bench_single(1000000);
bench_batch(10000);
bench_mixed_sizes(100000);
bench_realloc(100000);
printf("\n-- multithreaded --\n");
bench_multithreaded();
printf("\ndone\n");
#ifdef USE_CUSTOM
allocator_print_stats();
#endif
return 0;
}