2 // Copyright (c) 2010-2019 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef _HANDLE_LAT_H_
18 #define _HANDLE_LAT_H_
24 #include "task_base.h"
27 #define LATENCY_ACCURACY 1
28 // If ACCURACY_WINDOW is too small, the accuracy for packet N can be received by lat BEFORE
29 // packet N is received (re-ordering) resulting in accuracy being unused
30 // 8192 packets is equivalent to 550 micro-seconds at 10Gbps for 64 bytes packets
31 #define ACCURACY_WINDOW 8192
32 #define LAT_BUCKET_COUNT 128
34 #define LAT_BUCKET_COUNT 128
36 #define LAT_BUCKET_COUNT 128
39 uint64_t tot_all_pkts;
44 unsigned __int128 var_lat; /* variance */
45 uint64_t accuracy_limit_tsc;
47 uint64_t max_lat_error;
48 uint64_t min_lat_error;
49 uint64_t tot_lat_error;
50 unsigned __int128 var_lat_error;
52 uint64_t buckets[LAT_BUCKET_COUNT];
54 uint64_t lost_packets;
60 static struct time_unit lat_test_get_accuracy_limit(struct lat_test *lat_test)
62 return tsc_to_time_unit(lat_test->accuracy_limit_tsc);
65 static struct time_unit_err lat_test_get_avg(struct lat_test *lat_test)
70 tsc = lat_test->tot_lat/lat_test->tot_pkts;
71 tsc_error = lat_test->tot_lat_error/lat_test->tot_pkts;
73 struct time_unit_err ret = {
74 .time = tsc_to_time_unit(tsc),
75 .error = tsc_to_time_unit(tsc_error),
81 static struct time_unit_err lat_test_get_min(struct lat_test *lat_test)
83 struct time_unit_err ret = {
84 .time = tsc_to_time_unit(lat_test->min_lat),
85 .error = tsc_to_time_unit(lat_test->min_lat_error),
91 static struct time_unit_err lat_test_get_max(struct lat_test *lat_test)
93 struct time_unit_err ret = {
94 .time = tsc_to_time_unit(lat_test->max_lat),
95 .error = tsc_to_time_unit(lat_test->max_lat_error),
101 static struct time_unit_err lat_test_get_stddev(struct lat_test *lat_test)
103 unsigned __int128 avg_tsc = lat_test->tot_lat/lat_test->tot_pkts;
104 unsigned __int128 avg_tsc_squared = avg_tsc * avg_tsc;
105 unsigned __int128 avg_squares_tsc = lat_test->var_lat/lat_test->tot_pkts;
107 /* The assumption is that variance fits into 64 bits, meaning
108 that standard deviation fits into 32 bits. In other words,
109 the assumption is that the standard deviation is not more
110 than approximately 1 second. */
111 uint64_t var_tsc = avg_squares_tsc - avg_tsc_squared;
112 uint64_t stddev_tsc = sqrt(var_tsc);
114 unsigned __int128 avg_tsc_error = lat_test->tot_lat_error / lat_test->tot_pkts;
115 unsigned __int128 avg_tsc_squared_error = 2 * avg_tsc * avg_tsc_error + avg_tsc_error * avg_tsc_error;
116 unsigned __int128 avg_squares_tsc_error = lat_test->var_lat_error / lat_test->tot_pkts;
118 uint64_t var_tsc_error = avg_squares_tsc_error + avg_tsc_squared_error;
120 /* sqrt(a+-b) = sqrt(a) +- (-sqrt(a) + sqrt(a + b)) */
122 uint64_t stddev_tsc_error = - stddev_tsc + sqrt(var_tsc + var_tsc_error);
124 struct time_unit_err ret = {
125 .time = tsc_to_time_unit(stddev_tsc),
126 .error = tsc_to_time_unit(stddev_tsc_error),
132 static void _lat_test_histogram_combine(struct lat_test *dst, struct lat_test *src)
134 for (size_t i = 0; i < sizeof(dst->buckets)/sizeof(dst->buckets[0]); ++i)
135 dst->buckets[i] += src->buckets[i];
138 static void lat_test_combine(struct lat_test *dst, struct lat_test *src)
140 dst->tot_all_pkts += src->tot_all_pkts;
142 dst->tot_pkts += src->tot_pkts;
144 dst->tot_lat += src->tot_lat;
145 dst->tot_lat_error += src->tot_lat_error;
147 /* (a +- b)^2 = a^2 +- (2ab + b^2) */
148 dst->var_lat += src->var_lat;
149 dst->var_lat_error += src->var_lat_error;
151 if (src->max_lat > dst->max_lat) {
152 dst->max_lat = src->max_lat;
153 dst->max_lat_error = src->max_lat_error;
155 if (src->min_lat < dst->min_lat) {
156 dst->min_lat = src->min_lat;
157 dst->min_lat_error = src->min_lat_error;
160 if (src->accuracy_limit_tsc > dst->accuracy_limit_tsc)
161 dst->accuracy_limit_tsc = src->accuracy_limit_tsc;
162 dst->lost_packets += src->lost_packets;
163 dst->mis_ordered += src->mis_ordered;
164 dst->extent += src->extent;
165 dst->duplicate += src->duplicate;
167 #ifdef LATENCY_HISTOGRAM
168 _lat_test_histogram_combine(dst, src);
172 static void lat_test_reset(struct lat_test *lat_test)
174 lat_test->tot_all_pkts = 0;
175 lat_test->tot_pkts = 0;
176 lat_test->max_lat = 0;
177 lat_test->min_lat = -1;
178 lat_test->tot_lat = 0;
179 lat_test->var_lat = 0;
180 lat_test->max_lat_error = 0;
181 lat_test->min_lat_error = 0;
182 lat_test->tot_lat_error = 0;
183 lat_test->var_lat_error = 0;
184 lat_test->accuracy_limit_tsc = 0;
186 lat_test->lost_packets = 0;
187 lat_test->mis_ordered = 0;
188 lat_test->extent = 0;
189 lat_test->duplicate = 0;
191 memset(lat_test->buckets, 0, sizeof(lat_test->buckets));
194 static void lat_test_copy(struct lat_test *dst, struct lat_test *src)
196 if (src->tot_all_pkts)
197 memcpy(dst, src, sizeof(struct lat_test));
202 struct lat_test *task_lat_get_latency_meassurement(struct task_lat *task);
203 uint32_t task_lat_get_latency_bucket_size(struct task_lat *task);
204 void task_lat_use_other_latency_meassurement(struct task_lat *task);
205 void task_lat_set_accuracy_limit(struct task_lat *task, uint32_t accuracy_limit_nsec);
207 #endif /* _HANDLE_LAT_H_ */