Motr  M0
stats.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 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 
24 #ifndef __KERNEL__
25 #include <limits.h> /* ULONG_MAX */
26 #else
27 #include <linux/kernel.h> /* ULONG_MAX */
28 #endif
29 
30 #include "lib/misc.h" /* M0_SET0 */
31 #include "ut/ut.h" /* M0_UT_ASSERT */
32 
33 #include "motr/magic.h" /* M0_NET_TEST_TIMESTAMP_MAGIC */
34 
35 #include "net/test/stats.h"
36 
37 enum {
38  STATS_ONE_MILLION = 1000000,
39  STATS_BUF_LEN = 0x100,
42  TIMESTAMP_SEQ = 123456,
43 };
44 
46  unsigned long se_count;
47  unsigned long se_min;
48  unsigned long se_max;
49 #ifndef __KERNEL__
50  double se_sum;
51  double se_avg;
52  double se_stddev;
53 #else
54  unsigned se_sum:1;
55  unsigned se_avg:1;
56  unsigned se_stddev:1;
57 #endif
58 };
59 
60 #ifndef __KERNEL__
61 static bool is_in_eps_neighborhood(double a, double b)
62 {
63  const double eps = 1E-5;
64 
65  return a * (1. - eps) <= b && b <= a * (1. + eps);
66 }
67 #endif
68 
69 static void sample_check(struct m0_net_test_stats *stats,
70  struct stats_expected *expected)
71 {
72  unsigned long ul;
73 #ifndef __KERNEL__
74  double d;
75 #endif
76 
77  M0_PRE(stats != NULL);
78  M0_PRE(expected != NULL);
79 
80  M0_UT_ASSERT(stats->nts_count == expected->se_count);
81 
83  M0_UT_ASSERT(ul == expected->se_min);
84 
86  M0_UT_ASSERT(ul == expected->se_max);
87 
88 #ifndef __KERNEL__
91 
94 
97 #endif
98 }
99 
101 {
102  struct m0_net_test_stats stats2;
103  char bv_buf[STATS_BUF_LEN];
104  void *bv_addr = bv_buf;
105  m0_bcount_t bv_len = STATS_BUF_LEN;
106  struct m0_bufvec bv = M0_BUFVEC_INIT_BUF(&bv_addr, &bv_len);
107  m0_bcount_t serialized_len;
108  m0_bcount_t len;
109  struct stats_expected expected;
110 
112  stats, &bv,
114  M0_UT_ASSERT(serialized_len > 0);
115  M0_SET0(&stats2);
116 
118  &stats2, &bv, STATS_BUF_OFFSET);
119  M0_UT_ASSERT(len == serialized_len);
120 
121  expected.se_count = stats->nts_count;
124 #ifndef __KERNEL__
128 #endif
129  sample_check(&stats2, &expected);
130 }
131 
133  unsigned long *arr,
134  unsigned long arr_len)
135 {
136  unsigned long i;
137 
138  M0_PRE(stats != NULL);
139  for (i = 0; i < arr_len; ++i) {
142  }
143 }
144 
145 #define STATS_SAMPLE(sample_name) \
146  static unsigned long sample_name ## _sample[]
147 
148 #define STATS__EXPECTED(sample_name, count, min, max, sum, avg, stddev) \
149  static struct stats_expected sample_name ## _expected = { \
150  .se_count = (count), \
151  .se_min = (min), \
152  .se_max = (max), \
153  .se_sum = (sum), \
154  .se_avg = (avg), \
155  .se_stddev = (stddev), \
156  }
157 
158 #ifndef __KERNEL__
159 #define STATS_EXPECTED STATS__EXPECTED
160 #else
161 #define STATS_EXPECTED(sample_name, count, min, max, sum, avg, stddev) \
162  STATS__EXPECTED(sample_name, count, min, max, 0, 0, 0)
163 #endif
164 
165 #define STATS_SAMPLE_ADD(stats_name, sample_name) \
166  do { \
167  add_one_by_one(stats_name, sample_name ## _sample, \
168  ARRAY_SIZE(sample_name ## _sample)); \
169  } while (0)
170 
171 #define STATS_CHECK(stats_name, sample_name) \
172  sample_check(stats_name, &sample_name ## _expected)
173 
174 #define STATS_ADD_CHECK(stats_name, sample_name) \
175  do { \
176  STATS_SAMPLE_ADD(stats_name, sample_name); \
177  STATS_CHECK(stats_name, sample_name); \
178  } while (0)
179 
180 
181 STATS_SAMPLE(one_value) = { 1 };
182 STATS_EXPECTED(one_value, 1, 1, 1, 1., 1., 0.);
183 
184 STATS_SAMPLE(five_values) = { 1, 2, 3, 4, 5 };
185 STATS_EXPECTED(five_values, 5, 1, 5, 15., 3., 1.58113883);
186 
187 STATS_EXPECTED(zero_values, 0, 0, 0, 0., 0., 0.);
188 
189 STATS_EXPECTED(million_values, STATS_ONE_MILLION,
190  ULONG_MAX, ULONG_MAX, 1. * ULONG_MAX * STATS_ONE_MILLION,
191  ULONG_MAX, 0.);
192 
193 STATS_EXPECTED(one_plus_five_values, 6, 1, 5, 16., 16./6, 1.632993161);
194 
195 static void stats_time_ut(void)
196 {
197  struct m0_net_test_stats stats;
198  m0_time_t time;
199  int i;
200 
202  /* sample: .5s, 1.5s, 2.5s, 3.5s, 4.5s */
203  for (i = 0; i < 5; ++i) {
204  m0_net_test_stats_time_add(&stats, m0_time(i, 500000000));
206  }
207  /* check */
209  M0_UT_ASSERT(m0_time_seconds(time) == 0);
210  M0_UT_ASSERT(m0_time_nanoseconds(time) == 500000000);
212  M0_UT_ASSERT(m0_time_seconds(time) == 4);
213  M0_UT_ASSERT(m0_time_nanoseconds(time) == 500000000);
214 #ifndef __KERNEL__
216  M0_UT_ASSERT(m0_time_seconds(time) == 12);
217  M0_UT_ASSERT(m0_time_nanoseconds(time) == 500000000);
219  M0_UT_ASSERT(m0_time_seconds(time) == 2);
220  M0_UT_ASSERT(m0_time_nanoseconds(time) == 500000000);
222  M0_UT_ASSERT(m0_time_seconds(time) == 1);
223  M0_UT_ASSERT(581138830 <= m0_time_nanoseconds(time) &&
224  581138840 >= m0_time_nanoseconds(time));
225 #endif
226 }
227 
229 {
230  struct m0_net_test_stats stats;
231  struct m0_net_test_stats stats2;
232  int i;
233 
234  /* test #0: no elements in sample */
236  STATS_CHECK(&stats, zero_values);
238  /* test #1: one value in sample */
240  STATS_ADD_CHECK(&stats, one_value);
241  /* test #2: five values in sample */
243  STATS_ADD_CHECK(&stats, five_values);
244  /* test #3: one million identical values */
246  for (i = 0; i < STATS_ONE_MILLION; ++i)
247  m0_net_test_stats_add(&stats, ULONG_MAX);
248  STATS_CHECK(&stats, million_values);
249  /* test #4: six values */
251  STATS_SAMPLE_ADD(&stats, one_value);
252  STATS_SAMPLE_ADD(&stats, five_values);
253  STATS_CHECK(&stats, one_plus_five_values);
254  /* test #5: merge two stats */
256  STATS_SAMPLE_ADD(&stats, one_value);
257  m0_net_test_stats_reset(&stats2);
258  STATS_SAMPLE_ADD(&stats2, five_values);
260  STATS_CHECK(&stats, one_plus_five_values);
261  /* test #6: merge two stats, second is empty */
263  STATS_SAMPLE_ADD(&stats, one_value);
264  m0_net_test_stats_reset(&stats2);
266  STATS_CHECK(&stats, one_value);
267  /* test #7: merge two stats, first is empty */
269  m0_net_test_stats_reset(&stats2);
270  STATS_SAMPLE_ADD(&stats2, five_values);
272  STATS_CHECK(&stats, five_values);
273  /* test #8: test stats_time functions */
274  stats_time_ut();
275 }
276 
278 {
279  struct m0_net_test_timestamp ts;
280  struct m0_net_test_timestamp ts1;
281  m0_time_t before;
282  m0_time_t after;
283  m0_bcount_t serialized_len;
284  m0_bcount_t len;
285  char bv_buf[TIMESTAMP_BUF_LEN];
286  void *bv_addr = bv_buf;
288  struct m0_bufvec bv = M0_BUFVEC_INIT_BUF(&bv_addr, &bv_len);
289 
290  before = m0_time_now();
292  after = m0_time_now();
293 
294  M0_UT_ASSERT(ts.ntt_time >= before);
295  M0_UT_ASSERT(after >= ts.ntt_time);
298 
300  &ts, &bv, 0);
301  M0_UT_ASSERT(serialized_len > 0);
302  M0_SET0(&ts1);
304  &ts1, &bv, 0);
305  M0_UT_ASSERT(serialized_len == len);
306  M0_UT_ASSERT(ts.ntt_time == ts1.ntt_time);
307  M0_UT_ASSERT(ts1.ntt_magic == ts.ntt_magic);
308  M0_UT_ASSERT(ts1.ntt_seq == ts.ntt_seq);
309 }
310 
311 /*
312  * Local variables:
313  * c-indentation-style: "K&R"
314  * c-basic-offset: 8
315  * tab-width: 8
316  * fill-column: 79
317  * scroll-step: 1
318  * End:
319  */
uint64_t ntt_magic
Definition: stats.h:207
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
m0_bcount_t m0_net_test_stats_serialize(enum m0_net_test_serialize_op op, struct m0_net_test_stats *stats, struct m0_bufvec *bv, m0_bcount_t bv_offset)
Definition: stats.c:135
#define M0_PRE(cond)
void m0_net_test_timestamp_init(struct m0_net_test_timestamp *t, uint64_t seq)
Definition: stats.c:185
m0_time_t ntt_time
Definition: stats.h:209
#define NULL
Definition: misc.h:38
uint64_t ntt_seq
Definition: stats.h:211
void m0_net_test_timestamp_ut(void)
Definition: stats.c:277
uint64_t m0_time_t
Definition: time.h:37
static void sample_check(struct m0_net_test_stats *stats, struct stats_expected *expected)
Definition: stats.c:69
uint64_t m0_time_nanoseconds(const m0_time_t time)
Definition: time.c:89
void m0_net_test_stats_reset(struct m0_net_test_stats *stats)
Definition: stats.c:46
double m0_net_test_stats_avg(const struct m0_net_test_stats *stats)
Definition: stats_u.c:50
#define STATS_SAMPLE_ADD(stats_name, sample_name)
Definition: stats.c:165
uint64_t m0_bcount_t
Definition: types.h:77
#define M0_SET0(obj)
Definition: misc.h:64
double m0_net_test_stats_sum(const struct m0_net_test_stats *stats)
Definition: stats_u.c:43
m0_time_t m0_time(uint64_t secs, long ns)
Definition: time.c:41
unsigned long m0_net_test_stats_max(const struct m0_net_test_stats *stats)
Definition: stats.c:117
m0_bcount_t m0_net_test_timestamp_serialize(enum m0_net_test_serialize_op op, struct m0_net_test_timestamp *t, struct m0_bufvec *bv, m0_bcount_t bv_offset)
Definition: stats.c:200
unsigned long se_count
Definition: stats.c:46
static int expected
Definition: locality.c:102
static void stats_time_ut(void)
Definition: stats.c:195
int i
Definition: dir.c:1033
m0_time_t m0_net_test_stats_time_stddev(struct m0_net_test_stats *stats)
Definition: stats_u.c:101
m0_time_t m0_net_test_stats_time_avg(struct m0_net_test_stats *stats)
Definition: stats_u.c:96
m0_time_t m0_time_now(void)
Definition: time.c:134
double se_avg
Definition: stats.c:51
#define STATS_EXPECTED
Definition: stats.c:159
unsigned long se_max
Definition: stats.c:48
static bool is_in_eps_neighborhood(double a, double b)
Definition: stats.c:61
m0_time_t m0_net_test_stats_time_sum(struct m0_net_test_stats *stats)
Definition: stats_u.c:91
#define STATS_CHECK(stats_name, sample_name)
Definition: stats.c:171
double se_stddev
Definition: stats.c:52
uint64_t m0_time_seconds(const m0_time_t time)
Definition: time.c:83
Definition: module.c:67
m0_time_t m0_net_test_stats_time_min(struct m0_net_test_stats *stats)
Definition: stats.c:166
static void stats_serialize_ut(struct m0_net_test_stats *stats)
Definition: stats.c:100
#define STATS_SAMPLE(sample_name)
Definition: stats.c:145
m0_time_t m0_net_test_stats_time_max(struct m0_net_test_stats *stats)
Definition: stats.c:171
Definition: beck.c:130
unsigned long se_min
Definition: stats.c:47
#define STATS_ADD_CHECK(stats_name, sample_name)
Definition: stats.c:174
unsigned long m0_net_test_stats_min(const struct m0_net_test_stats *stats)
Definition: stats.c:110
static void add_one_by_one(struct m0_net_test_stats *stats, unsigned long *arr, unsigned long arr_len)
Definition: stats.c:132
void m0_net_test_stats_add_stats(struct m0_net_test_stats *stats, const struct m0_net_test_stats *stats2)
Definition: stats.c:91
void m0_net_test_stats_ut(void)
Definition: stats.c:228
void m0_net_test_stats_add(struct m0_net_test_stats *stats, unsigned long value)
Definition: stats.c:69
#define M0_UT_ASSERT(a)
Definition: ut.h:46
double se_sum
Definition: stats.c:50
double m0_net_test_stats_stddev(const struct m0_net_test_stats *stats)
Definition: stats_u.c:60
Definition: vec.h:145
void m0_net_test_stats_time_add(struct m0_net_test_stats *stats, m0_time_t time)
Definition: stats.c:161