702c29d94b857f4ef40746f147dcec4496cb1b7f
[deb_dpdk.git] / doc / guides / prog_guide / metrics_lib.rst
1 ..  BSD LICENSE
2     Copyright(c) 2017 Intel Corporation. All rights reserved.
3     All rights reserved.
4
5     Redistribution and use in source and binary forms, with or without
6     modification, are permitted provided that the following conditions
7     are met:
8
9     * Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11     * Redistributions in binary form must reproduce the above copyright
12     notice, this list of conditions and the following disclaimer in
13     the documentation and/or other materials provided with the
14     distribution.
15     * Neither the name of Intel Corporation nor the names of its
16     contributors may be used to endorse or promote products derived
17     from this software without specific prior written permission.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 .. _Metrics_Library:
32
33 Metrics Library
34 ===============
35
36 The Metrics library implements a mechanism by which *producers* can
37 publish numeric information for later querying by *consumers*. In
38 practice producers will typically be other libraries or primary
39 processes, whereas consumers will typically be applications.
40
41 Metrics themselves are statistics that are not generated by PMDs. Metric
42 information is populated using a push model, where producers update the
43 values contained within the metric library by calling an update function
44 on the relevant metrics. Consumers receive metric information by querying
45 the central metric data, which is held in shared memory.
46
47 For each metric, a separate value is maintained for each port id, and
48 when publishing metric values the producers need to specify which port is
49 being updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
50 that is intended for global statistics that are not associated with any
51 individual device. Since the metrics library is self-contained, the only
52 restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
53 - there is no requirement for the ports to actually exist.
54
55 Initialising the library
56 ------------------------
57
58 Before the library can be used, it has to be initialized by calling
59 ``rte_metrics_init()`` which sets up the metric store in shared memory.
60 This is where producers will publish metric information to, and where
61 consumers will query it from.
62
63 .. code-block:: c
64
65     rte_metrics_init(rte_socket_id());
66
67 This function **must** be called from a primary process, but otherwise
68 producers and consumers can be in either primary or secondary processes.
69
70 Registering metrics
71 -------------------
72
73 Metrics must first be *registered*, which is the way producers declare
74 the names of the metrics they will be publishing. Registration can either
75 be done individually, or a set of metrics can be registered as a group.
76 Individual registration is done using ``rte_metrics_reg_name()``:
77
78 .. code-block:: c
79
80     id_1 = rte_metrics_reg_name("mean_bits_in");
81     id_2 = rte_metrics_reg_name("mean_bits_out");
82     id_3 = rte_metrics_reg_name("peak_bits_in");
83     id_4 = rte_metrics_reg_name("peak_bits_out");
84
85 or alternatively, a set of metrics can be registered together using
86 ``rte_metrics_reg_names()``:
87
88 .. code-block:: c
89
90     const char * const names[] = {
91         "mean_bits_in", "mean_bits_out",
92         "peak_bits_in", "peak_bits_out",
93     };
94     id_set = rte_metrics_reg_names(&names[0], 4);
95
96 If the return value is negative, it means registration failed. Otherwise
97 the return value is the *key* for the metric, which is used when updating
98 values. A table mapping together these key values and the metrics' names
99 can be obtained using ``rte_metrics_get_names()``.
100
101 Updating metric values
102 ----------------------
103
104 Once registered, producers can update the metric for a given port using
105 the ``rte_metrics_update_value()`` function. This uses the metric key
106 that is returned when registering the metric, and can also be looked up
107 using ``rte_metrics_get_names()``.
108
109 .. code-block:: c
110
111     rte_metrics_update_value(port_id, id_1, values[0]);
112     rte_metrics_update_value(port_id, id_2, values[1]);
113     rte_metrics_update_value(port_id, id_3, values[2]);
114     rte_metrics_update_value(port_id, id_4, values[3]);
115
116 if metrics were registered as a single set, they can either be updated
117 individually using ``rte_metrics_update_value()``, or updated together
118 using the ``rte_metrics_update_values()`` function:
119
120 .. code-block:: c
121
122     rte_metrics_update_value(port_id, id_set, values[0]);
123     rte_metrics_update_value(port_id, id_set + 1, values[1]);
124     rte_metrics_update_value(port_id, id_set + 2, values[2]);
125     rte_metrics_update_value(port_id, id_set + 3, values[3]);
126
127     rte_metrics_update_values(port_id, id_set, values, 4);
128
129 Note that ``rte_metrics_update_values()`` cannot be used to update
130 metric values from *multiple* *sets*, as there is no guarantee two
131 sets registered one after the other have contiguous id values.
132
133 Querying metrics
134 ----------------
135
136 Consumers can obtain metric values by querying the metrics library using
137 the ``rte_metrics_get_values()`` function that return an array of
138 ``struct rte_metric_value``. Each entry within this array contains a metric
139 value and its associated key. A key-name mapping can be obtained using the
140 ``rte_metrics_get_names()`` function that returns an array of
141 ``struct rte_metric_name`` that is indexed by the key. The following will
142 print out all metrics for a given port:
143
144 .. code-block:: c
145
146     void print_metrics() {
147         struct rte_metric_name *names;
148         int len;
149
150         len = rte_metrics_get_names(NULL, 0);
151         if (len < 0) {
152             printf("Cannot get metrics count\n");
153             return;
154         }
155         if (len == 0) {
156             printf("No metrics to display (none have been registered)\n");
157             return;
158         }
159         metrics = malloc(sizeof(struct rte_metric_value) * len);
160         names =  malloc(sizeof(struct rte_metric_name) * len);
161         if (metrics == NULL || names == NULL) {
162             printf("Cannot allocate memory\n");
163             free(metrics);
164             free(names);
165             return;
166         }
167         ret = rte_metrics_get_values(port_id, metrics, len);
168         if (ret < 0 || ret > len) {
169             printf("Cannot get metrics values\n");
170             free(metrics);
171             free(names);
172             return;
173         }
174         printf("Metrics for port %i:\n", port_id);
175         for (i = 0; i < len; i++)
176             printf("  %s: %"PRIu64"\n",
177                 names[metrics[i].key].name, metrics[i].value);
178         free(metrics);
179         free(names);
180     }
181
182
183 Bit-rate statistics library
184 ---------------------------
185
186 The bit-rate library calculates the exponentially-weighted moving
187 average and peak bit-rates for each active port (i.e. network device).
188 These statistics are reported via the metrics library using the
189 following names:
190
191     - ``mean_bits_in``: Average inbound bit-rate
192     - ``mean_bits_out``:  Average outbound bit-rate
193     - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed)
194     - ``ewma_bits_out``:  Average outbound bit-rate (EWMA smoothed)
195     - ``peak_bits_in``:  Peak inbound bit-rate
196     - ``peak_bits_out``:  Peak outbound bit-rate
197
198 Once initialised and clocked at the appropriate frequency, these
199 statistics can be obtained by querying the metrics library.
200
201 Initialization
202 ~~~~~~~~~~~~~~
203
204 Before the library can be used, it has to be initialised by calling
205 ``rte_stats_bitrate_create()``, which will return a bit-rate
206 calculation object. Since the bit-rate library uses the metrics library
207 to report the calculated statistics, the bit-rate library then needs to
208 register the calculated statistics with the metrics library. This is
209 done using the helper function ``rte_stats_bitrate_reg()``.
210
211 .. code-block:: c
212
213     struct rte_stats_bitrates *bitrate_data;
214
215     bitrate_data = rte_stats_bitrate_create();
216     if (bitrate_data == NULL)
217         rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
218     rte_stats_bitrate_reg(bitrate_data);
219
220 Controlling the sampling rate
221 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222
223 Since the library works by periodic sampling but does not use an
224 internal thread, the application has to periodically call
225 ``rte_stats_bitrate_calc()``. The frequency at which this function
226 is called should be the intended sampling rate required for the
227 calculated statistics. For instance if per-second statistics are
228 desired, this function should be called once a second.
229
230 .. code-block:: c
231
232     tics_datum = rte_rdtsc();
233     tics_per_1sec = rte_get_timer_hz();
234
235     while( 1 ) {
236         /* ... */
237         tics_current = rte_rdtsc();
238         if (tics_current - tics_datum >= tics_per_1sec) {
239             /* Periodic bitrate calculation */
240             for (idx_port = 0; idx_port < cnt_ports; idx_port++)
241                     rte_stats_bitrate_calc(bitrate_data, idx_port);
242                 tics_datum = tics_current;
243             }
244         /* ... */
245     }
246
247
248 Latency statistics library
249 --------------------------
250
251 The latency statistics library calculates the latency of packet
252 processing by a DPDK application, reporting the minimum, average,
253 and maximum nano-seconds that packet processing takes, as well as
254 the jitter in processing delay. These statistics are then reported
255 via the metrics library using the following names:
256
257     - ``min_latency_ns``: Minimum processing latency (nano-seconds)
258     - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
259     - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
260     - ``jitter_ns``: Variance in processing latency (nano-seconds)
261
262 Once initialised and clocked at the appropriate frequency, these
263 statistics can be obtained by querying the metrics library.
264
265 Initialization
266 ~~~~~~~~~~~~~~
267
268 Before the library can be used, it has to be initialised by calling
269 ``rte_latencystats_init()``.
270
271 .. code-block:: c
272
273     lcoreid_t latencystats_lcore_id = -1;
274
275     int ret = rte_latencystats_init(1, NULL);
276     if (ret)
277         rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
278
279
280 Triggering statistic updates
281 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282
283 The ``rte_latencystats_update()`` function needs to be called
284 periodically so that latency statistics can be updated.
285
286 .. code-block:: c
287
288     if (latencystats_lcore_id == rte_lcore_id())
289         rte_latencystats_update();
290
291 Library shutdown
292 ~~~~~~~~~~~~~~~~
293
294 When finished, ``rte_latencystats_uninit()`` needs to be called to
295 de-initialise the latency library.
296
297 .. code-block:: c
298
299     rte_latencystats_uninit();