-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbench.c
342 lines (279 loc) · 10.2 KB
/
bench.c
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include <unistd.h>
#include <getopt.h>
#include <time.h>
#include "mem.h"
#include "mem_impl.h"
// use only while testing.
#undef testMode
// This is where we keep track of all the memory addresses we allocated
// so that we can free them later.
typedef struct memRecordStruct {
void* memAddress;
int memSize;
} memRecordType;
// how many of the records above we are going to have
#define MAX_MEM_RECORDS 10000
// memory-record table
static memRecordType * memRecord;
// how many records in the table
static int numRecords;
// total amount of memory acquired from system.
static int totalMemorySize;
static void displayStats(double cpu_time_used, int lastPercent);
/******************************************************************************************
*
* Procedure: main
* *
* Command line options:
*
* -n: ntrials
* -g: pctget
* -p: pctlarge
* -s: small_limit
* -l: large_limit
* -r: random_seed
*
* ntrials: total number of getmem plus freemem calls to randomly perform during this test. Default 10000.
* pctget: percent of the total getmem/freemem calls that should be getmem. Default 50.
* pctlarge: percent of the getmem calls that should request "large" blocks with a size greater than small_limit. Default 10.
* small_limit: largest size in bytes of a "small" block. Default 200.
* large_limit: largest size in bytes of a "large" block. Default 20000.
* random_seed: initial seed value for the random number generator. Default: some more-or-less random number such as the the system time-of-day clock (or bytes read from /dev/urandom if you're feeling adventurous).
* *
******************************************************************************************/
int main(int argc, char **argv) {
int c;
int ntrials;
int pctget;
int pctlarge;
int small_limit;
int large_limit;
int random_seed;
int cindx;
int rvalue;
int numBytes;
int lastPercent;
char * memAddress;
clock_t startTime, endTime;
double cpu_time_used;
FILE *Fdesc;
#ifdef testMode
int i;
uintptr_t total_size;
uintptr_t total_free;
uintptr_t n_free_blocks;
#endif
// allocate memory for our memory table
memRecord = malloc(MAX_MEM_RECORDS * sizeof(memRecordType));
numRecords = 0;
totalMemorySize = 0;
ntrials = 10000;
pctget = 50;
pctlarge = 10;
small_limit = 200;
large_limit = 20000;
random_seed = time(NULL);
cpu_time_used = 0;
while ((c = getopt(argc, argv, "n:g:p:s:l:r:")) != -1) {
switch (c) {
case 'n':
ntrials = atoi(optarg);
break;
case 'g':
pctget = atoi(optarg);
break;
case 'p':
pctlarge = atoi(optarg);
break;
case 's':
small_limit = atoi(optarg);
break;
case 'l':
large_limit = atoi(optarg);
break;
case 'r':
random_seed = atoi(optarg);
break;
case '?':
if (optopt == 'n' || optopt == 'g' || optopt == 'p'\
|| optopt == 'l' || optopt == 's' || optopt == 'r')
printf("Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
printf("Unknown option `-%c'.\n", optopt);
else
printf("Unknown option character `\\x%x'.\n", optopt);
return 1;
default:
abort();
}
}
srand(random_seed);
printf("ntrials = [%d], pctget = [%d], pctlarge = [%d], "
"small_limit = [%d], large_limit = [%d], random_seed = [%d]\n",
ntrials, pctget, pctlarge, small_limit, large_limit, random_seed);
if ((pctget < 0) || (pctget > 100)) {
printf("pctget should be between 0 and 100.\n");
exit(1);
}
if ((pctlarge < 0) || (pctlarge > 100)) {
printf("pctlarge should be between 0 and 100.\n");
exit(1);
}
startTime = clock();
#ifdef testMode
/*{
// basic test 1.
memRecord[0] = getmem(0x200);
check_heap();
freemem(memRecord[0]);
check_heap();
*/
// basic test 2.
/*
for (i = 0; i < 10; i++) {
memRecord[i].size = ((rand() % 1000) + 2000);
memRecord[i].memAddress = getmem(memRecord[i].size);
printf("Client Address:[%lu], memory size: [%lu]\n", (uintptr_t) memRecord[i].memAddress, (uintptr_t) memRecord[i].size);
check_heap();
}
*/
// basic test 3.
for (i = 0; i < 10; i++) {
memRecord[i].memSize = ((rand() % 1000) + 2000);
memRecord[i].memAddress = getmem(memRecord[i].memSize);
printf("Test3: Client addresses : [%lu], memory size: [%lu]\n",
(uintptr_t) memRecord[i].memAddress, (uintptr_t) memRecord[i].memSize);
check_heap();
}
for (i = 0; i < 10; i++) {
freemem(memRecord[i].memAddress);
printf("Test3: Client addresses : [%lu]\n", \
(uintptr_t) memRecord[i].memAddress);
check_heap();
}
get_mem_stats(&total_size, &total_free, &n_free_blocks);
printf("get_mem_stats returns: total_size:[%lu]"\
"total_free:[%lu] n_free_blocks:[%lu]\n", \
total_size, total_free, n_free_blocks);
return (0);
}
#endif
lastPercent = 0;
for (cindx = 0; cindx < ntrials; cindx++) {
rvalue = rand();
// generate a randome value between 0 and 100
rvalue %= 100;
// if this is going to be a getmem
if (rvalue <= pctget) {
// if there are still room in the table
if (numRecords < MAX_MEM_RECORDS) {
rvalue = rand();
// generate a random value between 0 and 100
rvalue %= 100;
// if this is going to be a large block.
if (rvalue <= pctlarge) {
// generate a random number between small limit and large limit
rvalue = ((rvalue % (large_limit - small_limit))\
+ small_limit);
// this is going to be a small block
} else {
if (small_limit > 0) {
rvalue %= small_limit;
} else {
rvalue = MIN_MEMORY_SIZE;
}
}
memRecord[numRecords].memSize = rvalue;
// save the memory address in the memory table
memAddress = getmem(rvalue);
if (memAddress == NULL) {
continue;
}
// save the memory address in the memory table
memRecord[numRecords].memAddress = memAddress;
numBytes = memRecord[numRecords].memSize;
if (numBytes > 16) {
numBytes = 16;
}
memset(memAddress, 0xFE, numBytes);
totalMemorySize += rvalue;
// update the number of records in the table.
numRecords++;
}
} else {
if (numRecords > 0) {
// Select a random memory address record from our table, free it.
rvalue = rand();
rvalue %= numRecords;
freemem(memRecord[rvalue].memAddress);
// Delete the freed record by moving the
// last record over it. And shortening the list.
memcpy(&memRecord[rvalue], &memRecord[numRecords - 1], \
sizeof(memRecordType));
numRecords--;
}
}
endTime = clock();
cpu_time_used = (endTime - startTime);
// if the percentage we are
// at right now has passed the (last percentage + 10)
if (((100 * cindx) / ntrials) >= (lastPercent + 10)) {
lastPercent += 10;
displayStats(cpu_time_used, lastPercent);
}
}
if (lastPercent <= 100) {
lastPercent += 10;
displayStats(cpu_time_used, lastPercent);
}
free(memRecord);
Fdesc = fopen("test.txt", "wb");
if (Fdesc != NULL) {
print_heap(Fdesc);
fclose(Fdesc);
}
return (0);
}
/******************************************************************************************
* *
* Procedure: displayStats *
* *
******************************************************************************************/
static void displayStats(double cpu_time_used, int lastPercent) {
int averageBlockSize;
int cindx;
double numSeconds;
// the total size of all memory allocated from the system.
uintptr_t total_size;
// the total amount of free memory
uintptr_t total_free;
uintptr_t n_free_blocks;
numSeconds = (cpu_time_used / CLOCKS_PER_SEC);
averageBlockSize = 0;
// The average block size is the sum of all
// the block sizes over number of records.
for (cindx = 0; cindx < numRecords; cindx++) {
averageBlockSize += memRecord[cindx].memSize;
}
if (numRecords > 0) {
averageBlockSize /= numRecords;
}
get_mem_stats(&total_size, &total_free, &n_free_blocks);
printf("Percentage: %d%%\n", lastPercent);
printf("Total CPU time used by the benchmark test"\
" so far in seconds: %.4f\n", numSeconds);
printf("Total amount of storage acquired from the"\
" underlying system by the memory manager durin"\
"g the test so far: %lu\n", total_size);
printf("Total number of blocks on the free storag"
"e list at this point in the test: %lu\n", n_free_blocks);
printf("Average number of bytes in the free stora"
"ge blocks at this point in the test: %.4f\n\n", \
total_free / (double) n_free_blocks);
}