-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.c
More file actions
239 lines (186 loc) · 5.94 KB
/
benchmark.c
File metadata and controls
239 lines (186 loc) · 5.94 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "allocator.h"
#define NUM_ITERATIONS 100000
#define MAX_ALLOC_SIZE 4096
/* Benchmark custom allocator */
double benchmark_custom_allocator(void) {
clock_t start = clock();
void* ptrs[1000] = {NULL};
for (int i = 0; i < NUM_ITERATIONS; i++) {
int idx = i % 1000;
size_t size = (rand() % MAX_ALLOC_SIZE) + 1;
if (ptrs[idx]) {
mem_free(ptrs[idx]);
}
ptrs[idx] = mem_malloc(size);
if (ptrs[idx]) {
memset(ptrs[idx], 0, size);
}
}
/* Free all remaining allocations */
for (int i = 0; i < 1000; i++) {
if (ptrs[i]) {
mem_free(ptrs[i]);
}
}
clock_t end = clock();
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
/* Benchmark system malloc */
double benchmark_system_malloc(void) {
clock_t start = clock();
void* ptrs[1000] = {NULL};
for (int i = 0; i < NUM_ITERATIONS; i++) {
int idx = i % 1000;
size_t size = (rand() % MAX_ALLOC_SIZE) + 1;
if (ptrs[idx]) {
free(ptrs[idx]);
}
ptrs[idx] = malloc(size);
if (ptrs[idx]) {
memset(ptrs[idx], 0, size);
}
}
/* Free all remaining allocations */
for (int i = 0; i < 1000; i++) {
if (ptrs[i]) {
free(ptrs[i]);
}
}
clock_t end = clock();
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
/* Benchmark calloc */
double benchmark_calloc(void) {
clock_t start = clock();
for (int i = 0; i < NUM_ITERATIONS / 10; i++) {
size_t nmemb = rand() % 100 + 1;
size_t size = rand() % 100 + 1;
void* ptr = mem_calloc(nmemb, size);
mem_free(ptr);
}
clock_t end = clock();
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
/* Benchmark realloc */
double benchmark_realloc(void) {
clock_t start = clock();
void* ptr = NULL;
for (int i = 0; i < NUM_ITERATIONS / 10; i++) {
size_t size = rand() % MAX_ALLOC_SIZE + 1;
ptr = mem_realloc(ptr, size);
if (ptr) {
memset(ptr, i & 0xFF, size);
}
}
mem_free(ptr);
clock_t end = clock();
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
/* Test fragmentation */
void test_fragmentation(void) {
printf("\n=== Fragmentation Test ===\n");
mem_reset();
void* ptrs[100];
/* Allocate many blocks */
for (int i = 0; i < 100; i++) {
ptrs[i] = mem_malloc(128);
}
/* Free every other block */
for (int i = 0; i < 100; i += 2) {
mem_free(ptrs[i]);
ptrs[i] = NULL;
}
printf("After freeing every other block:\n");
mem_print_stats();
/* Allocate larger blocks to test coalescing */
for (int i = 0; i < 100; i += 2) {
ptrs[i] = mem_malloc(256);
}
printf("\nAfter allocating larger blocks:\n");
mem_print_stats();
/* Free all */
for (int i = 0; i < 100; i++) {
if (ptrs[i]) {
mem_free(ptrs[i]);
}
}
printf("\nAfter freeing all:\n");
mem_print_stats();
}
/* Test various allocation sizes */
void test_allocation_sizes(void) {
printf("\n=== Allocation Size Test ===\n");
mem_reset();
size_t sizes[] = {1, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
8192, 16384, 32768, 65536, 131072, 262144};
int num_sizes = sizeof(sizes) / sizeof(sizes[0]);
for (int i = 0; i < num_sizes; i++) {
void* ptr = mem_malloc(sizes[i]);
printf("Allocated %zu bytes: %s\n", sizes[i], ptr ? "SUCCESS" : "FAILED");
if (ptr) {
memset(ptr, 0xFF, sizes[i]);
mem_free(ptr);
}
}
mem_print_stats();
}
/* Test edge cases */
void test_edge_cases(void) {
printf("\n=== Edge Cases Test ===\n");
mem_reset();
/* Test NULL and zero size */
void* p1 = mem_malloc(0);
printf("malloc(0): %s\n", p1 == NULL ? "NULL (correct)" : "non-NULL");
/* Test free(NULL) */
mem_free(NULL);
printf("free(NULL): completed without crash\n");
/* Test realloc edge cases */
void* p2 = mem_realloc(NULL, 100);
printf("realloc(NULL, 100): %s\n", p2 ? "SUCCESS" : "FAILED");
mem_free(p2);
void* p3 = mem_malloc(100);
void* p4 = mem_realloc(p3, 0);
printf("realloc(ptr, 0): %s\n", p4 == NULL ? "NULL (correct)" : "non-NULL");
/* Test calloc overflow */
size_t huge_size = (size_t)-1; /* SIZE_MAX */
void* p5 = mem_calloc(huge_size, 2);
printf("calloc overflow check: %s\n", p5 == NULL ? "NULL (correct)" : "non-NULL");
mem_print_stats();
}
int main(void) {
srand(time(NULL));
printf("Custom Memory Allocator Benchmark Suite\n");
printf("========================================\n\n");
/* Run allocation size tests */
test_allocation_sizes();
/* Run edge case tests */
test_edge_cases();
/* Run fragmentation test */
test_fragmentation();
/* Run performance benchmarks */
printf("\n=== Performance Benchmarks ===\n");
mem_reset();
double custom_time = benchmark_custom_allocator();
printf("Custom allocator: %.3f seconds\n", custom_time);
mem_print_stats();
printf("\n");
double system_time = benchmark_system_malloc();
printf("System malloc: %.3f seconds\n", system_time);
double ratio = custom_time / system_time;
printf("\nPerformance ratio (custom/system): %.2fx\n", ratio);
/* Calloc benchmark */
printf("\n");
mem_reset();
double calloc_time = benchmark_calloc();
printf("Calloc benchmark: %.3f seconds\n", calloc_time);
/* Realloc benchmark */
printf("\n");
mem_reset();
double realloc_time = benchmark_realloc();
printf("Realloc benchmark: %.3f seconds\n", realloc_time);
return 0;
}