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
|
#include <assert.h>
#include <malloc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static size_t _rand() {
static __thread size_t seed = 123456789;
size_t a = 1103515245;
size_t c = 12345;
size_t m = 1 << 31;
seed = (a * seed + c) % m;
return seed;
}
/*
* Available Benchmarks:
* 1.x: do malloc()/free() in a loop
* 1: simple loop
* 1.1: keep num_kept_allocations befor freeing
* 1.2: keep num_kept_allocations then free all stored
*/
typedef struct ThreadArgs {
double benchmark;
int allocations;
int num_kept_allocations;
int max_size;
} ThreadArgs;
static void* malloc_then_write(size_t size) {
void* ptr = malloc(size);
// Write to ptr
*((char*)ptr) = '!';
return ptr;
}
static void read_then_free(void* ptr) {
// Read before free
char s __attribute__((unused)) = *((char*)ptr);
free(ptr);
}
static void* test_thread_func(void* arg) {
ThreadArgs* args = (ThreadArgs*)arg;
void** ptrs = (void**)calloc(args->num_kept_allocations, sizeof(void*));
for(int i = 0; i < args->allocations; i++) {
int pos = i % args->num_kept_allocations;
if (args->benchmark == 1.1) {
if (i >= args->num_kept_allocations) {
read_then_free(ptrs[pos]);
}
}
if (args->benchmark == 1.2) {
if (pos == 0 && ptrs[pos] != NULL) {
for (int y = 0; y < args->num_kept_allocations; y++) {
read_then_free(ptrs[y]);
}
}
}
ptrs[pos] = malloc_then_write((_rand() % args->max_size) + 1);
if (args->benchmark == 1.0) {
read_then_free(ptrs[pos]);
}
}
return NULL;
}
int main(int argc, char* argv[]) {
pthread_t* threads;
int num_threads;
struct ThreadArgs thread_args;
if (argc < 7) {
fprintf(stderr, "Usage: %s <benchmark> <num threads> <num allocations> <max size> <num of stored allocations> <print mem stats> [<output-file>]\n", argv[0]);
return 1;
}
thread_args.benchmark = atof(argv[1]);
num_threads = atoi(argv[2]);
thread_args.allocations = atoi(argv[3]);
thread_args.max_size = atoi(argv[4]);
thread_args.num_kept_allocations = atoi(argv[5]);
threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
for (int i = 0; i < num_threads; i++) {
if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args)) {
perror("pthread_create");
return 1;
}
}
for(int i = 0; i < num_threads; i++) {
if (0 != pthread_join(threads[i], NULL)) {
perror("pthread_join");
return 1;
}
}
if (strcmp(argv[6], "yes") == 0)
{
char buf[4096];
FILE* status = fopen("/proc/self/status", "r");
if (status == NULL)
{
perror("fopen status");
exit(1);
}
FILE* output = stdout;
if (argc == 8)
{
output = fopen(argv[7], "w");
if (output == NULL)
{
perror("fopen output file");
exit(1);
}
}
while (!feof(status))
{
fgets(&buf, 4096, status);
fprintf(output, "%s", buf);
}
fclose(status);
}
return 0;
}
|