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 
23 #ifndef __KERNEL__
24 #include <limits.h> /* CHAR_MAX */
25 #else
26 #include <linux/kernel.h> /* INT_MIN */
27 #endif
28 
29 #include "lib/misc.h" /* M0_SET0 */
30 #include "lib/arith.h" /* min_check */
31 
32 #include "motr/magic.h" /* M0_NET_TEST_TIMESTAMP_MAGIC */
33 
34 #include "net/test/stats.h"
35 
47 {
48  M0_SET0(stats);
50 }
51 
53 {
54  static const struct m0_uint128 zero = {
55  .u_hi = 0,
56  .u_lo = 0
57  };
58 
59  if (stats == NULL)
60  return false;
61  if (stats->nts_count == 0 &&
62  (stats->nts_min != 0 || stats->nts_max != 0 ||
63  !m0_uint128_eq(&stats->nts_sum, &zero) ||
64  !m0_uint128_eq(&stats->nts_sum_sqr, &zero)))
65  return false;
66  return true;
67 }
68 
70  unsigned long value)
71 {
72  struct m0_uint128 v128;
73 
75 
76  stats->nts_count++;
77  if (stats->nts_count == 1) {
78  stats->nts_min = value;
79  stats->nts_max = value;
80  } else {
81  stats->nts_min = min_check(stats->nts_min, value);
82  stats->nts_max = max_check(stats->nts_max, value);
83  }
84  M0_CASSERT(sizeof value <= sizeof stats->nts_sum.u_hi);
85  m0_uint128_add(&stats->nts_sum, &stats->nts_sum,
86  &M0_UINT128(0, value));
87  m0_uint128_mul64(&v128, value, value);
88  m0_uint128_add(&stats->nts_sum_sqr, &stats->nts_sum_sqr, &v128);
89 }
90 
92  const struct m0_net_test_stats *stats2)
93 {
96 
97  if (stats->nts_count == 0) {
98  stats->nts_min = stats2->nts_min;
99  stats->nts_max = stats2->nts_max;
100  } else if (stats2->nts_count != 0) {
101  stats->nts_min = min_check(stats->nts_min, stats2->nts_min);
102  stats->nts_max = max_check(stats->nts_max, stats2->nts_max);
103  }
104  stats->nts_count += stats2->nts_count;
105  m0_uint128_add(&stats->nts_sum, &stats->nts_sum, &stats2->nts_sum);
106  m0_uint128_add(&stats->nts_sum_sqr, &stats->nts_sum_sqr,
107  &stats2->nts_sum_sqr);
108 }
109 
110 unsigned long m0_net_test_stats_min(const struct m0_net_test_stats *stats)
111 {
113 
114  return stats->nts_min;
115 }
116 
117 unsigned long m0_net_test_stats_max(const struct m0_net_test_stats *stats)
118 {
120 
121  return stats->nts_max;
122 }
123 
125  FIELD_DESCR(struct m0_net_test_stats, nts_count),
126  FIELD_DESCR(struct m0_net_test_stats, nts_min),
127  FIELD_DESCR(struct m0_net_test_stats, nts_max),
128 };
129 
131  FIELD_DESCR(struct m0_uint128, u_hi),
132  FIELD_DESCR(struct m0_uint128, u_lo),
133 };
134 
136  struct m0_net_test_stats *stats,
137  struct m0_bufvec *bv,
138  m0_bcount_t bv_offset)
139 {
140  struct m0_uint128 * const pv128[] = {
141  &stats->nts_sum,
142  &stats->nts_sum_sqr,
143  };
144  m0_bcount_t len_total;
145  m0_bcount_t len;
146  int i;
147 
150  bv, bv_offset);
151  len_total = net_test_len_accumulate(0, len);
152  for (i = 0; i < ARRAY_SIZE(pv128) && len_total != 0; ++i) {
153  len = m0_net_test_serialize(op, pv128[i],
155  bv, bv_offset + len_total);
156  len_total = net_test_len_accumulate(len_total, len);
157  }
158  return len_total;
159 }
160 
162 {
163  m0_net_test_stats_add(stats, (unsigned long)time);
164 }
165 
167 {
169 }
170 
172 {
174 }
175 
186 {
187  M0_PRE(t != NULL);
188 
189  t->ntt_seq = seq;
190  t->ntt_magic = M0_NET_TEST_TIMESTAMP_MAGIC;
191  t->ntt_time = m0_time_now();
192 }
193 
195  FIELD_DESCR(struct m0_net_test_timestamp, ntt_magic),
196  FIELD_DESCR(struct m0_net_test_timestamp, ntt_time),
197  FIELD_DESCR(struct m0_net_test_timestamp, ntt_seq),
198 };
199 
201  struct m0_net_test_timestamp *t,
202  struct m0_bufvec *bv,
203  m0_bcount_t bv_offset)
204 {
205  m0_bcount_t len;
206 
208 
209  len = m0_net_test_serialize(op, t,
211  bv, bv_offset);
212  return op == M0_NET_TEST_DESERIALIZE ?
213  t->ntt_magic == M0_NET_TEST_TIMESTAMP_MAGIC ? len : 0 : len;
214 }
215 
228  unsigned long messages,
229  m0_time_t timestamp,
230  m0_time_t interval)
231 {
232  M0_PRE(mps != NULL);
233 
235 
236  mps->ntmps_last_nr = messages;
237  mps->ntmps_last_time = timestamp;
238  mps->ntmps_time_interval = interval;
239 }
240 
242  unsigned long messages,
243  m0_time_t timestamp)
244 {
245  unsigned long messages_delta;
246  m0_time_t time_delta;
247  m0_time_t time_next;
248  uint64_t time_delta_ns;
249  unsigned long m_per_sec;
250  unsigned i;
251  static const struct {
252  unsigned long pow;
253  unsigned long value;
254  } pow10[] = {
255  { .pow = 1000000000, .value = ULONG_MAX / 1000000000 },
256  { .pow = 100000000, .value = ULONG_MAX / 100000000 },
257  { .pow = 10000000, .value = ULONG_MAX / 10000000 },
258  { .pow = 1000000, .value = ULONG_MAX / 1000000 },
259  { .pow = 100000, .value = ULONG_MAX / 100000 },
260  { .pow = 10000, .value = ULONG_MAX / 10000 },
261  { .pow = 1000, .value = ULONG_MAX / 1000 },
262  { .pow = 100, .value = ULONG_MAX / 100 },
263  { .pow = 10, .value = ULONG_MAX / 10 },
264  { .pow = 1, .value = ULONG_MAX },
265  };
266 
267  M0_PRE(mps != NULL);
268  M0_PRE(messages >= mps->ntmps_last_nr);
269  M0_PRE(timestamp >= mps->ntmps_last_time);
270 
271  messages_delta = messages - mps->ntmps_last_nr;
272  time_delta = m0_time_sub(timestamp, mps->ntmps_last_time);
273  time_next = m0_time_add(mps->ntmps_last_time,
274  mps->ntmps_time_interval);
275 
276  if (timestamp < time_next)
277  return time_next;
278 
279  mps->ntmps_last_nr = messages;
281  mps->ntmps_last_time = time_next;
282 
283  time_delta_ns = m0_time_seconds(time_delta) * M0_TIME_ONE_SECOND +
284  m0_time_nanoseconds(time_delta);
285  /*
286  To measure bandwidth in messages/sec it needs to be calculated
287  (messages_delta / time_delta_ns) * 1'000'000'000 =
288  (messages_delta * 1'000'000'000) / time_delta_ns =
289  ((messages_delta * (10^M)) / time_delta_ns) * (10^(9-M)),
290  where M is some parameter. To perform integer division M
291  should be maximized in range [0, 9] - in case if M < 9
292  there is a loss of precision.
293  */
294  for (i = 0; i < ARRAY_SIZE(pow10); ++i) {
295  if (messages_delta <= pow10[i].value)
296  break;
297  }
298  m_per_sec = (messages_delta * pow10[i].pow / time_delta_ns) *
299  (M0_TIME_ONE_SECOND / pow10[i].pow);
300  m0_net_test_stats_add(&mps->ntmps_stats, m_per_sec);
301 
302  return time_next;
303 }
304 
317  const struct m0_net_test_msg_nr *msg_nr2)
318 {
319  M0_PRE(msg_nr != NULL);
320  M0_PRE(msg_nr2 != NULL);
321 
322  msg_nr->ntmn_total += msg_nr2->ntmn_total;
323  msg_nr->ntmn_failed += msg_nr2->ntmn_failed;
324  msg_nr->ntmn_bad += msg_nr2->ntmn_bad;
325 }
326 
331 /*
332  * Local variables:
333  * c-indentation-style: "K&R"
334  * c-basic-offset: 8
335  * tab-width: 8
336  * fill-column: 79
337  * scroll-step: 1
338  * End:
339  */
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 ntmps_last_time
Definition: stats.h:254
#define NULL
Definition: misc.h:38
m0_bcount_t m0_net_test_serialize(enum m0_net_test_serialize_op op, void *obj, const struct m0_net_test_descr descr[], size_t descr_nr, struct m0_bufvec *bv, m0_bcount_t bv_offset)
Definition: serialize.c:176
#define ergo(a, b)
Definition: misc.h:293
unsigned long nts_max
Definition: stats.h:94
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
uint64_t m0_time_t
Definition: time.h:37
#define min_check(a, b)
Definition: arith.h:88
#define M0_CASSERT(cond)
uint64_t m0_time_nanoseconds(const m0_time_t time)
Definition: time.c:89
#define max_check(a, b)
Definition: arith.h:95
void m0_net_test_stats_reset(struct m0_net_test_stats *stats)
Definition: stats.c:46
struct m0_uint128 nts_sum_sqr
Definition: stats.h:98
int const char const void * value
Definition: dir.c:325
uint64_t u_lo
Definition: types.h:58
void m0_net_test_msg_nr_add(struct m0_net_test_msg_nr *msg_nr, const struct m0_net_test_msg_nr *msg_nr2)
Definition: stats.c:316
uint64_t m0_bcount_t
Definition: types.h:77
static m0_bcount_t net_test_len_accumulate(m0_bcount_t accumulator, m0_bcount_t addend)
Definition: serialize.h:122
#define M0_SET0(obj)
Definition: misc.h:64
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
op
Definition: libdemo.c:64
static const struct m0_uint128 zero
Definition: misc.c:41
int i
Definition: dir.c:1033
size_t ntmn_bad
Definition: stats.h:322
TYPE_DESCR(m0_net_test_stats)
m0_time_t m0_time_now(void)
Definition: time.c:134
static struct m0_thread t[8]
Definition: service_ut.c:1230
uint64_t u_hi
Definition: types.h:57
m0_time_t m0_net_test_mps_add(struct m0_net_test_mps *mps, unsigned long messages, m0_time_t timestamp)
Definition: stats.c:241
uint64_t u_hi
Definition: types.h:36
unsigned long nts_count
Definition: stats.h:90
#define FIELD_DESCR(type, field)
Definition: serialize.h:63
#define M0_POST(cond)
m0_time_t ntmps_time_interval
Definition: stats.h:256
size_t ntmn_total
Definition: stats.h:308
m0_time_t m0_time_add(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:47
uint64_t m0_time_seconds(const m0_time_t time)
Definition: time.c:83
unsigned long nts_min
Definition: stats.h:92
void m0_net_test_mps_init(struct m0_net_test_mps *mps, unsigned long messages, m0_time_t timestamp, m0_time_t interval)
Definition: stats.c:227
m0_time_t m0_net_test_stats_time_min(struct m0_net_test_stats *stats)
Definition: stats.c:166
m0_time_t m0_net_test_stats_time_max(struct m0_net_test_stats *stats)
Definition: stats.c:171
M0_INTERNAL void m0_uint128_mul64(struct m0_uint128 *res, uint64_t a, uint64_t b)
Definition: misc.c:76
m0_net_test_serialize_op
Definition: serialize.h:42
Definition: beck.c:130
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
unsigned long ntmps_last_nr
Definition: stats.h:252
size_t ntmn_failed
Definition: stats.h:316
unsigned long m0_net_test_stats_min(const struct m0_net_test_stats *stats)
Definition: stats.c:110
bool m0_net_test_stats_invariant(const struct m0_net_test_stats *stats)
Definition: stats.c:52
#define M0_UINT128(hi, lo)
Definition: types.h:40
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_add(struct m0_net_test_stats *stats, unsigned long value)
Definition: stats.c:69
struct m0_uint128 nts_sum
Definition: stats.h:96
struct m0_net_test_stats ntmps_stats
Definition: stats.h:250
#define ARRAY_SIZE(a)
Definition: misc.h:45
uint64_t seq
Definition: common.c:97
M0_INTERNAL void m0_uint128_add(struct m0_uint128 *res, const struct m0_uint128 *a, const struct m0_uint128 *b)
Definition: misc.c:62
#define USE_TYPE_DESCR(type_name)
Definition: serialize.h:57
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