blob: 10b95989c99af9e5eba35fabb532b861361e7c05 [file] [log] [blame]
philippecabdbb52015-04-20 21:33:16 +00001#define _GNU_SOURCE
2#include <string.h>
3#include <pthread.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <unistd.h>
7#include <sys/types.h>
8
9// memrw provides a simulation of an application
10// reading and writing memory, for the sake of tuning helgrind.
11// It is a very simple (simplistic) model:
12// * only one thread
13// * only one exe context reading or writing the memory
14// * the working set of the application is unrealistically
15// concentrated on a consecutive nr of MB.
16// At this moment, it was just used to tune the EvM data structure
17// of helgrind.
18// It would be nice to enhance this program to cope with a richer
19// model e.g. multiple threads, many different stack traces touching
20// the memory, better working set distribution, ...
21
philippea1ac2f42015-05-01 17:12:00 +000022static int sz_b; // size of a block
23static int nr_b; // total nr of blocks used by the program
24static int nr_b_ws; // nr_b in program working set
25static int nr_loops; // nr of loops reading or writing the ws
philippecabdbb52015-04-20 21:33:16 +000026static int nr_thr; // nr of threads (hardcoded to 1 currently)
philippea1ac2f42015-05-01 17:12:00 +000027static int nr_repeat; // nr of times we will allocate, use, then free total+ws
philippecabdbb52015-04-20 21:33:16 +000028
philippea1ac2f42015-05-01 17:12:00 +000029// Note: the total nr of MB is what is explicitely allocated.
philippecabdbb52015-04-20 21:33:16 +000030// On top of that, we have the stacks, local vars, lib vars, ...
philippea1ac2f42015-05-01 17:12:00 +000031// The working set is just the first nr_b_ws blocks of nr_b.
philippecabdbb52015-04-20 21:33:16 +000032
33static int verbose = 0;
philippea1ac2f42015-05-01 17:12:00 +000034static unsigned char **t_b; // Pointers to all blocks
philippecabdbb52015-04-20 21:33:16 +000035
36static void *memrw_fn(void *v)
37{
38 int loops, m, b;
philippe71a04ea2015-04-30 20:30:12 +000039 int dowrite;
philippecabdbb52015-04-20 21:33:16 +000040 int differs = 0;
41 unsigned char prev = 0;
42
43 for (loops = 0; loops < nr_loops; loops++) {
philippe71a04ea2015-04-30 20:30:12 +000044 // printf("loop %d dowrite %d\n", loops, dowrite);
philippecabdbb52015-04-20 21:33:16 +000045 // Note: in case of multiple threads, we will have
46 // to add lock/unlock somewhere in the below, maybe to lock
47 // the MB we are reading or writing.
philippea1ac2f42015-05-01 17:12:00 +000048 for (m = 0; m < nr_b_ws; m++) {
49 for (b = 0; b < sz_b; b++) {
philippe71a04ea2015-04-30 20:30:12 +000050 dowrite = b % 5 == 0;
philippecabdbb52015-04-20 21:33:16 +000051 // Do some write or read operations.
philippe71a04ea2015-04-30 20:30:12 +000052 if (dowrite) {
philippea1ac2f42015-05-01 17:12:00 +000053 if (t_b[m][b] < 255)
54 t_b[m][b] += differs;
philippecabdbb52015-04-20 21:33:16 +000055 else
philippea1ac2f42015-05-01 17:12:00 +000056 t_b[m][b] = 0;
philippecabdbb52015-04-20 21:33:16 +000057 } else {
philippea1ac2f42015-05-01 17:12:00 +000058 differs = t_b[m][b] != prev;
59 prev = t_b[m][b];
philippecabdbb52015-04-20 21:33:16 +000060 }
61 }
62 }
63 }
64 return NULL;
65}
66
67int main (int argc, char *argv[])
68{
69 int a;
70 int ret;
71 int i;
philippea1ac2f42015-05-01 17:12:00 +000072 int r;
philippecabdbb52015-04-20 21:33:16 +000073 pthread_t thr;
74
philippea1ac2f42015-05-01 17:12:00 +000075 // usage: memrw [-b blocksize default 1MB ]
76 // [-t nr_b default 10] [-w nr_b_ws default 10]
philippecabdbb52015-04-20 21:33:16 +000077 // [-l nr_loops_on_ws default 3]
philippea1ac2f42015-05-01 17:12:00 +000078 // [-r nr_repeat default 1]
philippecabdbb52015-04-20 21:33:16 +000079 // [-f fan_out default 0]
80 // [-v verbosity default 0]
philippea1ac2f42015-05-01 17:12:00 +000081 sz_b = 1024 * 1024;
82 nr_b = 10;
83 nr_b_ws = 10;
philippecabdbb52015-04-20 21:33:16 +000084 nr_loops = 3;
philippea1ac2f42015-05-01 17:12:00 +000085 nr_repeat = 1;
philippecabdbb52015-04-20 21:33:16 +000086 verbose = 0;
87 for (a = 1; a < argc; a+=2) {
philippea1ac2f42015-05-01 17:12:00 +000088 if (strcmp(argv[a], "-b") == 0) {
89 sz_b = atoi(argv[a+1]);
90 } else if (strcmp(argv[a], "-t") == 0) {
91 nr_b = atoi(argv[a+1]);
philippecabdbb52015-04-20 21:33:16 +000092 } else if (strcmp(argv[a], "-w") == 0) {
philippea1ac2f42015-05-01 17:12:00 +000093 nr_b_ws = atoi(argv[a+1]);
philippecabdbb52015-04-20 21:33:16 +000094 } else if (strcmp(argv[a], "-l") == 0) {
95 nr_loops = atoi(argv[a+1]);
philippea1ac2f42015-05-01 17:12:00 +000096 } else if (strcmp(argv[a], "-r") == 0) {
97 nr_repeat = atoi(argv[a+1]);
philippecabdbb52015-04-20 21:33:16 +000098 } else if (strcmp(argv[a], "-v") == 0) {
99 verbose = atoi(argv[a+1]);
100 } else {
101 printf("unknown arg %s\n", argv[a]);
102 }
103 }
philippea1ac2f42015-05-01 17:12:00 +0000104 if (nr_b_ws > nr_b)
105 nr_b_ws = nr_b; // to make it easy to do loops combining values
philippecabdbb52015-04-20 21:33:16 +0000106
107 nr_thr = 1;
108
philippe016f2ee2015-05-06 21:24:23 +0000109 printf ("total program memory -t %llu MB"
110 " working set -w %llu MB\n",
111 ((unsigned long long)nr_b * sz_b)
112 / (unsigned long long) (1024*1024),
113 ((unsigned long long)nr_b_ws * sz_b)
114 / (unsigned long long)(1024*1024));
philippea1ac2f42015-05-01 17:12:00 +0000115 printf (" working set R or W -l %d times"
116 " repeat the whole stuff -r %d times\n",
117 nr_loops,
118 nr_repeat);
philippecabdbb52015-04-20 21:33:16 +0000119
philippea1ac2f42015-05-01 17:12:00 +0000120 for (r = 0; r < nr_repeat; r++) {
121 printf ("creating and initialising the total program memory\n");
122 t_b = malloc(nr_b * sizeof(char*));
123 if (t_b == NULL)
124 perror("malloc t_b");
125 for (i = 0; i < nr_b; i++) {
126 t_b[i] = calloc(sz_b, 1);
127 if (t_b[i] == NULL)
128 perror("malloc t_b[i]");
129 }
130
131 printf("starting thread that will read or write the working set\n");
132 ret = pthread_create(&thr, NULL, memrw_fn, &nr_thr);
133 if (ret != 0)
134 perror("pthread_create");
135 printf("waiting for thread termination\n");
136
137 ret = pthread_join(thr, NULL);
138 if (ret != 0)
139 perror("pthread_join");
140 printf("thread terminated\n");
141
142 /* Now, free the memory used, for the next repeat */
143 for (i = 0; i < nr_b; i++)
144 free (t_b[i]);
145 free (t_b);
146 printf("memory freed\n");
philippecabdbb52015-04-20 21:33:16 +0000147 }
148
philippecabdbb52015-04-20 21:33:16 +0000149 return 0;
150}