Motr  M0
ub.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-2021 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #ifndef _ISOC99_SOURCE
24 #define _ISOC99_SOURCE /* INFINITY */
25 #endif
26 
27 #include <stdio.h> /* printf */
28 #include <sys/time.h> /* gettimeofday */
29 #include <math.h> /* sqrt */
30 
31 #include "lib/misc.h" /* M0_SET0 */
32 #include "lib/errno.h"
33 #include "lib/time.h"
34 #include "lib/assert.h"
35 #include "lib/arith.h"
36 #include "lib/ub.h"
37 
43 static struct m0_ub_set *last = NULL;
44 
45 M0_INTERNAL void m0_ub_set_print(void)
46 {
47  const struct m0_ub_set *set;
48 
49  printf("Available benchmarks:\n");
50  for (set = last; set != NULL; set = set->us_prev)
51  printf("%s\n", set->us_name);
52 }
53 
54 M0_INTERNAL int m0_ub_set_select(const char *name)
55 {
56  struct m0_ub_set *set;
57 
58  for (set = last; set != NULL; set = set->us_prev) {
59  if (strcmp(set->us_name, name) == 0) {
60  last = set;
61  last->us_prev = NULL;
62  return 0;
63  }
64  }
65  printf("No such benchmark: %s\n", name);
66  return -ENOENT;
67 }
68 
69 M0_INTERNAL void m0_ub_set_add(struct m0_ub_set *set)
70 {
71  M0_PRE(set->us_prev == NULL);
72 
73  set->us_prev = last;
74  last = set;
75 }
76 
77 /* normalize struct timeval, so that microseconds field (tv_usec) is less than
78  one million */
79 static void timeval_norm(struct timeval *t)
80 {
81  while (t->tv_usec < 0) {
82  t->tv_sec--;
83  t->tv_usec += 1000000;
84  }
85  while (t->tv_usec >= 1000000) {
86  t->tv_sec++;
87  t->tv_usec -= 1000000;
88  }
89 }
90 
91 static void timeval_diff(const struct timeval *start, const struct timeval *end,
92  struct timeval *diff)
93 {
94  diff->tv_sec += end->tv_sec - start->tv_sec;
95  /* this relies on tv_usec being signed */
96  diff->tv_usec += end->tv_usec - start->tv_usec;
98 }
99 
100 static double delay(const struct timeval *start, const struct timeval *end)
101 {
102  struct timeval diff;
103 
104  M0_SET0(&diff);
105  timeval_diff(start, end, &diff);
106  return diff.tv_sec + ((double)diff.tv_usec)/1000000;
107 }
108 
109 static void ub_run_one(const struct m0_ub_set *set, struct m0_ub_bench *bench)
110 {
111  uint32_t i;
112  struct timeval start;
113  struct timeval end;
114  double sec;
115  m0_time_t stime;
116 
117  printf(".");
118  if (bench->ub_init != NULL)
119  bench->ub_init();
120  gettimeofday(&start, NULL);
121  stime = m0_time_now();
122 
123  for (i = 0; i < bench->ub_iter; ++i)
124  bench->ub_round(i);
125  gettimeofday(&end, NULL);
126  bench->ub_total_etime = m0_time_sub(m0_time_now(), stime);
127  if (bench->ub_fini != NULL)
128  bench->ub_fini();
129  sec = delay(&start, &end);
130  bench->ub_total += sec;
131  bench->ub_square += sec * sec;
132  bench->ub_max = max_type(double, bench->ub_max, sec);
133  bench->ub_min = min_type(double, bench->ub_min, sec);
134 }
135 
136 /* Return bandwidth in bytes per sec */
137 static uint64_t bw(uint64_t bytes, m0_time_t time)
138 {
139  return bytes * M0_TIME_ONE_MSEC / (time / 1000);
140 }
141 
142 static void results_print(uint32_t round)
143 {
144  const struct m0_ub_set *set;
145  const struct m0_ub_bench *bench;
146  double avg;
147  double std;
148  uint64_t kib = 0;
149  uint64_t kbs_per_op;
150  uint64_t bytes = 0;
151  uint64_t bw_kibps = 0;
152  uint64_t iops = 0;
153 
154  printf("\t%12.12s: [%7s] %6s %6s %6s %6s %8s %9s %11s %11s %12s %8s %8s %8s\n",
155  "bench", "iter", "min", "max", "avg", "std", "sec/op", "op/sec",
156  "block_size", "time_in_sec", "bytes", "KiB", "BW_KiB", "IOPS");
157  for (set = last; set != NULL; set = set->us_prev) {
158  printf("set: %s\n", set->us_name);
159  for (bench = &set->us_run[0]; bench->ub_name; ++bench) {
160  avg = bench->ub_total / round;
161  std = sqrt(bench->ub_square / round - avg * avg);
162  bytes = bench->ub_block_size * bench->ub_blocks_per_op * bench->ub_iter;
163  if (bytes > 0) {
164  kib = bytes / 1024;
165  bw_kibps = bw(bytes, bench->ub_total_etime) / 1024;
166  kbs_per_op = bench->ub_block_size * bench->ub_blocks_per_op;
167  iops = (bw_kibps * 1024) / kbs_per_op;
168  }
169 
170  printf("\t%12.12s: [%7i] %6.2f %6.2f %6.2f %5.2f%%"
171  " %8.3e/%8.3e %9.2"PRIu32" %11.2f %13.4" PRIu64 " "
172  "%8.2" PRIu64 " %8.2" PRIu64 " %8.2" PRIu64 "\n",
173  bench->ub_name, bench->ub_iter,
174  bench->ub_min, bench->ub_max, avg,
175  std * 100.0 / avg, avg / bench->ub_iter,
176  bench->ub_iter / avg, bench->ub_block_size,
177  bench->ub_total, bytes, kib, bw_kibps, iops);
178  }
179  }
180 }
181 
182 M0_INTERNAL int m0_ub_run(uint32_t rounds, const char *opts)
183 {
184  struct m0_ub_set *set;
185  struct m0_ub_bench *bench;
186  uint32_t round;
187  int rc = 0;
188 
189  for (set = last; set != NULL; set = set->us_prev) {
190  for (bench = &set->us_run[0]; bench->ub_name; ++bench) {
191  bench->ub_total = 0.0;
192  bench->ub_square = 0.0;
193  bench->ub_min = INFINITY;
194  bench->ub_max = 0.0;
195  }
196  }
197 
198  for (round = 1; round <= rounds; ++round) {
199  printf("-- round %"PRIu32" --\n", round);
200  for (set = last; set != NULL; set = set->us_prev) {
201  printf(" %s[", set->us_name);
202  if (set->us_init != NULL) {
203  rc = set->us_init(opts);
204  if (rc != 0)
205  goto end;
206  }
207  for (bench = &set->us_run[0]; bench->ub_name; ++bench)
208  ub_run_one(set, bench);
209  if (set->us_fini != NULL)
210  set->us_fini();
211  printf("]\n");
212  }
213  printf("\n");
214  results_print(round);
215  }
216 end:
217  if (rc != 0)
218  fprintf(stderr, "Benchmark initialisation failed: `%s',"
219  " rc=%d\n", set->us_name, rc);
220  return rc;
221 }
222 
225 /*
226  * Local variables:
227  * c-indentation-style: "K&R"
228  * c-basic-offset: 8
229  * tab-width: 8
230  * fill-column: 80
231  * scroll-step: 1
232  * End:
233  */
#define M0_PRE(cond)
static void results_print(uint32_t round)
Definition: ub.c:142
static int(* diff[M0_PARITY_CAL_ALGO_NR])(struct m0_parity_math *math, struct m0_buf *old, struct m0_buf *new, struct m0_buf *parity, uint32_t index)
Definition: parity_math.c:290
#define NULL
Definition: misc.h:38
double ub_min
Definition: ub.h:64
uint64_t m0_time_t
Definition: time.h:37
#define min_type(t, a, b)
Definition: arith.h:76
void(* ub_round)(int iter)
Definition: ub.h:50
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ub.h:42
uint32_t ub_blocks_per_op
Definition: ub.h:48
static void timeval_diff(const struct timeval *start, const struct timeval *end, struct timeval *diff)
Definition: ub.c:91
static struct m0_ub_set * last
Definition: ub.c:43
void(* ub_init)(void)
Definition: ub.h:52
int i
Definition: dir.c:1033
#define PRIu64
Definition: types.h:58
static double delay(const struct timeval *start, const struct timeval *end)
Definition: ub.c:100
const char * name
Definition: trace.c:110
M0_INTERNAL int m0_ub_run(uint32_t rounds, const char *opts)
Definition: ub.c:182
static uint64_t bw(uint64_t bytes, m0_time_t time)
Definition: ub.c:137
void(* ub_fini)(void)
Definition: ub.h:54
m0_time_t m0_time_now(void)
Definition: time.c:134
static struct m0_thread t[8]
Definition: service_ut.c:1230
struct m0_ub_set * us_prev
Definition: ub.h:91
const char * ub_name
Definition: ub.h:44
double ub_square
Definition: ub.h:62
double ub_max
Definition: ub.h:66
M0_INTERNAL int m0_ub_set_select(const char *name)
Definition: ub.c:54
uint32_t ub_block_size
Definition: ub.h:47
#define PRIu32
Definition: types.h:66
M0_INTERNAL void m0_ub_set_print(void)
Definition: ub.c:45
m0_time_t ub_total_etime
Definition: ub.h:60
static void timeval_norm(struct timeval *t)
Definition: ub.c:79
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
static int start(struct m0_fom *fom)
Definition: trigger_fom.c:321
#define max_type(t, a, b)
Definition: arith.h:82
uint32_t ub_iter
Definition: ub.h:46
int32_t rc
Definition: trigger_fop.h:47
Definition: ub.h:74
double ub_total
Definition: ub.h:59
M0_INTERNAL void m0_ub_set_add(struct m0_ub_set *set)
Definition: ub.c:69
static void ub_run_one(const struct m0_ub_set *set, struct m0_ub_bench *bench)
Definition: ub.c:109