Flow123d  release_3.0.0-1152-gdb4be9b
memory.cc
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4 #include <vector>
5 #include <chrono>
6 #include <iostream>
7 #include <fstream>
8 #include <stdarg.h>
9 #include "libs/json.hpp"
10 
11 #define KB 1024
12 #define MB 1048576
13 #define REP (MB * 3)
14 #define OFFSET 256
15 #define ARR_SIZE (MB * 100)
16 
17 #define GIGA 1.0e+9
18 #define MEGA 1.0e+6
19 #define KILO 1.0e+3
20 #define MILI 1.0e-3
21 #define MICRO 1.0e-6
22 #define NANO 1.0e-9
23 
24 #define CHAR_SIZE sizeof(char)
25 #define INT_SIZE sizeof(int)
26 
27 #define SHOW_DURATION true
28 #define SHOW_DETAILS true
29 
30 using namespace std;
32 
33 class Timer {
34 protected:
35  chrono::high_resolution_clock::time_point _start;
36  chrono::high_resolution_clock::time_point _stop;
37 public:
38  chrono::duration<double, nano> duration;
39  void start() {
40  this->_start = std::chrono::high_resolution_clock::now();
41  }
42  void stop() {
43  this->_stop = std::chrono::high_resolution_clock::now();
44  this->duration = chrono::duration_cast<chrono::nanoseconds>(this->_stop - this->_start);
45  }
46 };
47 
48 void printf_debug(const char * fmt, ...) {
49  string newfmt = string(fmt) + "\r";
50  const char * newfmt_c = newfmt.c_str();
51  va_list args;
52  va_start(args, fmt);
53  vprintf(newfmt_c, args);
54  va_end(args);
55  cout << flush;
56 }
57 
58 void cpu_test(json &results, int repetition = REP) {
59  Timer timer;
60  int i, sum;
61 
62  printf("-- running CPU REG test with %d k repetition\n", repetition / KB);
63 
64  //-------------------------------------------------------
65  timer.start();
66  for (i = 0; i < repetition; i++) {
67  sum += i;
68  }
69  timer.stop();
70  //-------------------------------------------------------
71 
72  if (SHOW_DURATION) {
73  results["duration"] = timer.duration.count();
74  }
75 
76  if (SHOW_DETAILS) {
77  results["reps"] = repetition;
78  }
79 
80  results["MB_per_sec"] = (repetition * INT_SIZE)/ (timer.duration.count() * NANO) / MEGA;
81 }
82 
83 
84 template <int N, int M>
85 void cpu_test_r(json &results, int (&arr)[M], int (&sizes)[N], int repetition = REP) {
86  Timer timer;
87  int i, j, mod, sum;
88  const int i_max = sizeof(sizes) / INT_SIZE;
89 
90  printf("-- running CPU R test with %d k repetition\n", repetition / KB);
91 
92  for (i = 0; i < i_max; i++) {
93  mod = sizes[i] - 1;
94  printf_debug("buffer size %9d kB...", sizes[i] / KB);
95 
96  //-------------------------------------------------------
97  timer.start();
98  for (j = 0; j < repetition; j++) {
99  sum += arr[(j * OFFSET) & mod];
100  }
101  timer.stop();
102  //-------------------------------------------------------
103 
104  if (SHOW_DURATION) {
105  results["duration"][to_string(sizes[i]/1024 * INT_SIZE)] = timer.duration.count() * NANO;
106  }
107 
108  results["MB_per_sec"][to_string(sizes[i]/1024 * INT_SIZE)] = (repetition * INT_SIZE)/ (timer.duration.count() * NANO) / MEGA;
109  }
110 
111  if (SHOW_DETAILS) {
112  results["reps"] = repetition;
113  results["size"] = sizeof(arr) / INT_SIZE;
114  results["sum"] = sum;
115  }
116 }
117 
118 
119 template <int N, int M>
120 void cpu_test_w(json &results, int (&arr)[M], int (&sizes)[N], int repetition = REP) {
121  Timer timer;
122  int i, j, mod;
123  const int i_max = sizeof(sizes) / INT_SIZE;
124 
125  printf("-- running CPU W test with %d k repetition\n", repetition / KB);
126 
127  for (i = 0; i < i_max; i++) {
128  mod = sizes[i] - 1;
129  printf_debug("buffer size %9d kB...", sizes[i] / KB);
130 
131  //-------------------------------------------------------
132  timer.start();
133  for (j = 0; j < repetition; j++) {
134  arr[(j * OFFSET) & mod] = 0;
135  }
136  timer.stop();
137  //-------------------------------------------------------
138 
139  if (SHOW_DURATION) {
140  results["duration"][to_string(sizes[i]/1024 * INT_SIZE)] = timer.duration.count() * NANO;
141  }
142 
143  results["MB_per_sec"][to_string(sizes[i]/1024 * INT_SIZE)] = (repetition * INT_SIZE)/ (timer.duration.count() * NANO) / MEGA;
144  }
145 
146  if (SHOW_DETAILS) {
147  results["reps"] = repetition;
148  results["size"] = sizeof(arr) / INT_SIZE;
149  }
150 }
151 
152 
153 template <int N, int M>
154 void cpu_test_rw(json &results, int (&arr)[M], int (&sizes)[N], int repetition = REP) {
155  Timer timer;
156  int i, j, mod, sum;
157  const int i_max = sizeof(sizes) / INT_SIZE;
158 
159  printf("-- running CPU R/W test with %d k repetition\n", repetition / KB);
160 
161  for (i = 0; i < i_max; i++) {
162  mod = sizes[i] - 1;
163  printf_debug("buffer size %9d kB...", sizes[i] / KB);
164 
165  //-------------------------------------------------------
166  timer.start();
167  for (j = 0; j < repetition; j++) {
168  arr[(j * OFFSET) & mod]++;
169  arr[(j * OFFSET) & mod]--;
170  }
171  timer.stop();
172  //-------------------------------------------------------
173 
174  if (SHOW_DURATION) {
175  results["duration"][to_string(sizes[i]/1024 * INT_SIZE)] = timer.duration.count() * NANO;
176  }
177 
178  results["MB_per_sec"][to_string(sizes[i]/1024 * INT_SIZE)] = (repetition * INT_SIZE)/ (timer.duration.count() * NANO) / MEGA;
179  }
180 
181  if (SHOW_DETAILS) {
182  results["reps"] = repetition;
183  results["size"] = sizeof(arr) * INT_SIZE;
184  }
185 }
186 
187 template <int N>
188 void io_test_rw(json &results, int (&sizes)[N], int file_size, const int buffer_size = 1 * MB) {
189  char *buffer = new char[buffer_size];
190  char *read_buffer;
191  Timer timer_r, timer_w;
192  ofstream write_stream;
193  ifstream read_stream;
194  string fname;
195  int repetition, i, j, k, i_max;
196  i_max = sizeof(sizes) / INT_SIZE;
197 
198  printf("-- running IO R/W bandwidth test with %1.3f MB file size\n", (float)file_size / MB);
199 
200  for (i = 0; i < i_max; i++) {
201  printf_debug("(%2d/%2d) buffer size %9.3f kB...", i + 1, i_max, (float)sizes[i] / KB);
202  repetition = file_size / (sizes[i] * CHAR_SIZE);
203  fname = "tmp_file_" + to_string(sizes[i]) + ".tmp";
204  read_buffer = new char[sizes[i]];
205 
206  // write file
207  write_stream.open(fname.c_str(), ios::binary | ios::out);
208 
209  //-------------------------------------------------------
210  timer_w.start();
211  for (int j = 0; j < repetition; j++) {
212  write_stream.write (buffer, sizes[i]);
213  }
214  timer_w.stop();
215  //-------------------------------------------------------
216 
217  if (write_stream.fail()) {
218  // buffer may be too big so ignore this
219  write_stream.close();
220  remove(fname.c_str());
221  continue;
222  } else {
223  write_stream.close();
224  }
225 
226  // read file
227  read_stream.open(fname.c_str(), ios::binary | ifstream::in);
228 
229  //-------------------------------------------------------
230  timer_r.start();
231  for (int j = 0; j < repetition; j++) {
232  read_stream.read (read_buffer, sizes[i]);
233  }
234  timer_r.stop();
235  //-------------------------------------------------------
236 
237  if (read_stream.fail()) {
238  // buffer may be too big so ignore this
239  read_stream.close();
240  remove(fname.c_str());
241  continue;
242  } else {
243  read_stream.close();
244  }
245 
246  remove(fname.c_str());
247 
248  if (SHOW_DURATION) {
249  results["write"]["duration"][to_string(sizes[i] * CHAR_SIZE)] = timer_w.duration.count() * NANO;
250  results["read"]["duration"][to_string(sizes[i] * CHAR_SIZE)] = timer_r.duration.count() * NANO;
251  }
252 
253  results["write"]["MB_per_sec"][to_string(sizes[i] * CHAR_SIZE)] = ((repetition * sizes[i])/timer_w.duration.count() / NANO) / MEGA;
254  results["read"]["MB_per_sec"][to_string(sizes[i] * CHAR_SIZE)] = ((repetition * sizes[i])/timer_r.duration.count() / NANO) / MEGA;
255  }
256 
257  if (SHOW_DETAILS) {
258  results["size"] = file_size;
259  }
260 }
261 
262 void io_test_many(json &results, int no_files = KILO) {
263  Timer timer_r, timer_w, timer_d;
264  ofstream write_stream;
265  ifstream read_stream;
266  string fname;
267  int i, n;
268 
269  printf("-- running IO R/W latency test with %d files\n", no_files);
270 
271  printf_debug("writing test...");
272 
273  //-------------------------------------------------------
274  timer_w.start();
275  for (i = 0; i < no_files; i++) {
276  fname = "tmp_file_" + to_string(i) + ".tmp";
277  write_stream.open(fname.c_str(), ios::binary | ios::out);
278  write_stream << 0;
279  write_stream.close();
280  }
281  timer_w.stop();
282  //-------------------------------------------------------
283 
284 
285  printf_debug("reading test...");
286 
287  //-------------------------------------------------------
288  timer_r.start();
289  for (i = 0; i < no_files; i++) {
290  fname = "tmp_file_" + to_string(i) + ".tmp";
291  read_stream.open(fname.c_str(), ios::binary | ios::in);
292  read_stream >> n;
293  read_stream.close();
294  }
295  timer_r.stop();
296  //-------------------------------------------------------
297 
298 
299  printf_debug("removing test...");
300 
301  //-------------------------------------------------------
302  timer_d.start();
303  // remove files
304  for (i = 0; i < no_files; i++) {
305  fname = "tmp_file_" + to_string(i) + ".tmp";
306  remove(fname.c_str());
307  }
308  timer_d.stop();
309  //-------------------------------------------------------
310 
311  if (SHOW_DURATION) {
312  results["write"]["duration"] = timer_w.duration.count() * NANO;
313  results["read"]["duration"] = timer_r.duration.count() * NANO;
314  results["del"]["duration"] = timer_d.duration.count() * NANO;
315  }
316 
317  results["write"]["k_files_per_sec"] = (float)no_files / (timer_w.duration.count() * NANO) / KILO;
318  results["read"]["k_files_per_sec"] = (float)no_files / (timer_r.duration.count() * NANO) / KILO;
319  results["del"]["k_files_per_sec"] = (float)no_files / (timer_d.duration.count() * NANO) / KILO;
320 
321  if (SHOW_DETAILS) {
322  results["count"] = no_files;
323  }
324 }
325 
326 
327 /**
328  * Start benchmark, usage:
329  * optional <output> file: will create json file output with results
330  * optional <scale> float: scales repetition count for benchmark
331  * default is 1, for example value 2 will run tests
332  * twice as many times, value 0.5 will experiments half
333  * as many times
334  */
335 int main(int argc, char* argv[]) {
336  map<int, long> results_write, results_read, results_rw, results_cpu;
337  int rep_cnt = (int)(argc >= 3 ? std::stof(argv[2]) * REP : 1 * REP);
338 
339  // chunk size for testing
340  static int sizes[] = {
341  // 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
342  1 * KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB, 32 * KB, 64 * KB, 128 * KB,
343  256 * KB, 512 * KB, 1 * MB, 2 * MB, 4 * MB, 8 * MB, 16 * MB, 32 * MB
344  // 4 * KB, 128 * KB, 8 * MB, 32 * MB
345  };
346 
347  // chunk size for testing
348  static int io_sizes[] = {
349  16, 32, 64, 128, 256, 512,
350  1 * KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB, 32 * KB, 64 * KB, 128 * KB,
351  256 * KB, 512 * KB, 1 * MB, 2 * MB, 4 * MB, 8 * MB
352  };
353 
354  // create and randomize array
355  printf_debug("creating array... ");
356  static int arr[ARR_SIZE];
357  printf_debug("randomizing array... ");
358  for (int i = 0; i < sizeof(arr)/sizeof(int); i++) {
359  arr[i] = (i * 13941) % 35; //13778941
360  }
361  printf_debug("running tests... ");
362  json results;
363 
364 
365  Timer test_timer;
366  test_timer.start();
367  cpu_test (results["cpu"]["reg"], rep_cnt * 100);
368  cpu_test_r (results["cpu"]["read"], arr, sizes, rep_cnt);
369  cpu_test_w (results["cpu"]["write"], arr, sizes, rep_cnt);
370  cpu_test_rw (results["cpu"]["rw"], arr, sizes, rep_cnt);
371  io_test_rw (results["io"]["band"], io_sizes, rep_cnt * 8);
372  io_test_many (results["io"]["lat"], (rep_cnt / REP) * KILO);
373  test_timer.stop();
374 
375  printf("---------------------------------\n");
376  printf("%-30s: %1.3f\n", "time taken", test_timer.duration.count() * NANO);
377 
378  printf_debug("generating output... \n");
379  printf(" ");
380  cout << results.dump(true) << endl;
381  if (argc >= 2) {
382  ofstream ofs (argv[1]);
383  ofs << results.dump(true) << endl;
384  }
385 
386  return 0;
387 }
#define KB
Definition: memory.cc:11
#define ARR_SIZE
Definition: memory.cc:15
#define SHOW_DETAILS
Definition: memory.cc:28
a class to store JSON values
Definition: json.hpp:173
void io_test_many(json &results, int no_files=KILO)
Definition: memory.cc:262
void cpu_test_w(json &results, int(&arr)[M], int(&sizes)[N], int repetition=REP)
Definition: memory.cc:120
bool read_stream(Istream_type &is, Value_type &value)
std::string to_string(const T &value)
Definition: string.h:29
#define REP
Definition: memory.cc:13
chrono::high_resolution_clock::time_point _stop
Definition: memory.cc:36
#define MEGA
Definition: memory.cc:18
#define OFFSET
Definition: memory.cc:14
void cpu_test(json &results, int repetition=REP)
Definition: memory.cc:58
void write_stream(const Value_type &value, Ostream_type &os, unsigned int options=0)
chrono::high_resolution_clock::time_point _start
Definition: memory.cc:35
void start()
Definition: memory.cc:39
void io_test_rw(json &results, int(&sizes)[N], int file_size, const int buffer_size=1 *MB)
Definition: memory.cc:188
#define CHAR_SIZE
Definition: memory.cc:24
#define KILO
Definition: memory.cc:19
int main(int argc, char *argv[])
Definition: memory.cc:335
void cpu_test_r(json &results, int(&arr)[M], int(&sizes)[N], int repetition=REP)
Definition: memory.cc:85
#define NANO
Definition: memory.cc:22
void cpu_test_rw(json &results, int(&arr)[M], int(&sizes)[N], int repetition=REP)
Definition: memory.cc:154
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2079
#define INT_SIZE
Definition: memory.cc:25
Definition: format.cc:82
#define MB
Definition: memory.cc:12
chrono::duration< double, nano > duration
Definition: memory.cc:38
basic_json<> json
default JSON class
Definition: json.hpp:8671
Definition: memory.cc:33
void printf_debug(const char *fmt,...)
Definition: memory.cc:48
void stop()
Definition: memory.cc:42
#define SHOW_DURATION
Definition: memory.cc:27
void printf(BasicWriter< Char > &w, BasicCStringRef< Char > format, ArgList args)
Definition: printf.h:444