]>
Commit | Line | Data |
---|---|---|
44c82814 JS |
1 | /* |
2 | * Copyright (c) 2018 Red Hat, Inc. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #include <config.h> | |
18 | #undef NDEBUG | |
19 | #include "stopwatch.h" | |
20 | #include <assert.h> | |
21 | #include <math.h> | |
22 | #include <stdio.h> | |
23 | #include "ovstest.h" | |
24 | #include "util.h" | |
25 | ||
26 | #define MAX_SAMPLES 100 | |
27 | #define UNIT SW_MS | |
28 | ||
29 | struct test_data { | |
30 | const char *name; | |
31 | unsigned long long samples[MAX_SAMPLES]; | |
32 | size_t num_samples; | |
33 | struct stopwatch_stats expected_stats; | |
34 | }; | |
35 | ||
36 | static struct test_data data_sets[] = { | |
37 | { | |
38 | .name = "1-interval-zero-length", | |
39 | .samples = { 0, 0 }, | |
40 | .num_samples = 2, | |
41 | .expected_stats = { | |
42 | .count = 1, | |
43 | .unit = UNIT, | |
44 | .max = 0, | |
45 | .min = 0, | |
46 | .pctl_95 = 0, | |
47 | .ewma_50 = 0, | |
48 | .ewma_1 = 0, | |
49 | }, | |
50 | }, | |
51 | { | |
52 | .name = "1-interval-unit-length", | |
53 | .samples = { 0, 1 }, | |
54 | .num_samples = 2, | |
55 | .expected_stats = { | |
56 | .count = 1, | |
57 | .unit = UNIT, | |
58 | .max = 1, | |
59 | .min = 1, | |
60 | .pctl_95 = 0, | |
61 | .ewma_50 = 1, | |
62 | .ewma_1 = 1, | |
63 | }, | |
64 | }, | |
65 | { | |
66 | .name = "10-intervals-unit-length", | |
67 | .samples = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, | |
68 | .num_samples = 11, | |
69 | .expected_stats = { | |
70 | .count = 10, | |
71 | .unit = UNIT, | |
72 | .max = 1, | |
73 | .min = 1, | |
74 | .pctl_95 = 1, | |
75 | .ewma_50 = 1, | |
76 | .ewma_1 = 1, | |
77 | }, | |
78 | }, | |
79 | { | |
80 | .name = "10-intervals-linear-growth", | |
81 | .samples = { 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56 }, | |
82 | .num_samples = 11, | |
83 | .expected_stats = { | |
84 | .count = 10, | |
85 | .unit = UNIT, | |
86 | .max = 10, | |
87 | .min = 1, | |
88 | .pctl_95 = 10.0, | |
89 | .ewma_50 = 9.0, | |
90 | .ewma_1 = 1.4, | |
91 | }, | |
92 | }, | |
93 | { | |
94 | .name = "60-intervals-unit-length", | |
95 | .samples = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, | |
96 | 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, | |
97 | 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, | |
98 | 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | |
99 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, | |
100 | 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, | |
101 | 61, }, | |
102 | .num_samples = 61, | |
103 | .expected_stats = { | |
104 | .count = 60, | |
105 | .unit = UNIT, | |
106 | .max = 1, | |
107 | .min = 1, | |
108 | .pctl_95 = 1, | |
109 | .ewma_50 = 1, | |
110 | .ewma_1 = 1, | |
111 | }, | |
112 | }, | |
113 | { | |
114 | .name = "60-intervals-linear-growth", | |
115 | .samples = { 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, | |
116 | 56, 67, 79, 92, 106, 121, 137, 154, 172, 191, | |
117 | 211, 232, 254, 277, 301, 326, 352, 379, 407, 436, | |
118 | 466, 497, 529, 562, 596, 631, 667, 704, 742, 781, | |
119 | 821, 862, 904, 947, 991, 1036, 1082, 1129, 1177, 1226, | |
120 | 1276, 1327, 1379, 1432, 1486, 1541, 1597, 1654, 1712, 1771, | |
121 | 1831, }, | |
122 | .num_samples = 61, | |
123 | .expected_stats = { | |
124 | .count = 60, | |
125 | .unit = UNIT, | |
126 | .max = 60, | |
127 | .min = 1, | |
128 | /* 95th percentile is actually closer to 57, but the estimate is | |
129 | * pretty dang close */ | |
130 | .pctl_95 = 56, | |
131 | .ewma_50 = 59, | |
132 | .ewma_1 = 15.7, | |
133 | }, | |
134 | }, | |
135 | }; | |
136 | ||
137 | #define ASSERT_MSG(COND, MSG, ...) \ | |
138 | if (!(COND)) { \ | |
139 | fprintf(stderr, MSG "\n", ##__VA_ARGS__); \ | |
140 | assert(COND); \ | |
141 | } | |
142 | ||
143 | #define ASSERT_ULL_EQ(a, b) \ | |
144 | ASSERT_MSG(a == b, \ | |
145 | "Assertion '%s == %s' failed: %llu == %llu", \ | |
146 | #a, #b, a, b) | |
147 | ||
148 | #define ASSERT_DOUBLE_EQ(a, b, eps) \ | |
149 | ASSERT_MSG(fabs(a - b) < eps, \ | |
150 | "Assertion '|%s - %s| < %s' failed: |%g - %g| < %g", \ | |
151 | #a, #b, #eps, a, b, eps) | |
152 | ||
153 | #define ASSERT_STATS_EQ(a, b) \ | |
154 | do { \ | |
155 | ASSERT_ULL_EQ((a)->count, (b)->count); \ | |
156 | ASSERT_ULL_EQ((a)->max, (b)->max); \ | |
157 | ASSERT_ULL_EQ((a)->min, (b)->min); \ | |
158 | ASSERT_DOUBLE_EQ((a)->pctl_95, (b)->pctl_95, 1e-1); \ | |
159 | ASSERT_DOUBLE_EQ((a)->ewma_50, (b)->ewma_50, 1e-1); \ | |
160 | ASSERT_DOUBLE_EQ((a)->ewma_1, (b)->ewma_1, 1e-1); \ | |
161 | } while (0) | |
162 | ||
163 | static void | |
164 | test_stopwatch_calculate_stats(void) | |
165 | { | |
166 | struct test_data *d; | |
167 | ||
168 | for (size_t i = 0; i < ARRAY_SIZE(data_sets); i++) { | |
169 | d = &data_sets[i]; | |
170 | ||
171 | fprintf(stderr, "TEST '%s'\n", d->name); | |
172 | ||
173 | stopwatch_create(d->name, UNIT); | |
174 | for (size_t j = 0; j < d->num_samples - 1; j ++) { | |
175 | stopwatch_start(d->name, d->samples[j]); | |
176 | stopwatch_stop(d->name, d->samples[j + 1]); | |
177 | } | |
178 | stopwatch_sync(); | |
179 | ||
180 | struct stopwatch_stats stats = { .unit = UNIT }; | |
181 | stopwatch_get_stats(d->name, &stats); | |
182 | ASSERT_STATS_EQ(&stats, &d->expected_stats); | |
183 | ||
184 | printf("."); | |
185 | } | |
186 | } | |
187 | ||
188 | static void | |
189 | test_stopwatch_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) | |
190 | { | |
191 | test_stopwatch_calculate_stats(); | |
192 | printf("\n"); | |
193 | } | |
194 | ||
195 | OVSTEST_REGISTER("test-stopwatch", test_stopwatch_main); |