New upstream version 17.11.5
[deb_dpdk.git] / test / test / test_pmd_ring_perf.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34
35 #include <stdio.h>
36 #include <inttypes.h>
37 #include <rte_ring.h>
38 #include <rte_cycles.h>
39 #include <rte_launch.h>
40 #include <rte_ethdev.h>
41 #include <rte_eth_ring.h>
42 #include <rte_bus_vdev.h>
43
44 #include "test.h"
45
46 #define RING_NAME "RING_PERF"
47 #define RING_SIZE 4096
48 #define MAX_BURST 32
49
50 /*
51  * the sizes to enqueue and dequeue in testing
52  * (marked volatile so they won't be seen as compile-time constants)
53  */
54 static const volatile unsigned bulk_sizes[] = { 1, 8, 32 };
55
56 /* The ring structure used for tests */
57 static struct rte_ring *r;
58 static uint16_t ring_ethdev_port;
59
60 /* Get cycle counts for dequeuing from an empty ring. Should be 2 or 3 cycles */
61 static void
62 test_empty_dequeue(void)
63 {
64         const unsigned iter_shift = 26;
65         const unsigned iterations = 1 << iter_shift;
66         unsigned i = 0;
67         void *burst[MAX_BURST];
68
69         const uint64_t sc_start = rte_rdtsc();
70         for (i = 0; i < iterations; i++)
71                 rte_ring_sc_dequeue_bulk(r, burst, bulk_sizes[0], NULL);
72         const uint64_t sc_end = rte_rdtsc();
73
74         const uint64_t eth_start = rte_rdtsc();
75         for (i = 0; i < iterations; i++)
76                 rte_eth_rx_burst(ring_ethdev_port, 0, (void *)burst,
77                                 bulk_sizes[0]);
78         const uint64_t eth_end = rte_rdtsc();
79
80         printf("Ring empty dequeue  : %.1F\n",
81                         (double)(sc_end - sc_start) / iterations);
82         printf("Ethdev empty dequeue: %.1F\n",
83                         (double)(eth_end - eth_start) / iterations);
84 }
85
86 /*
87  * Test function that determines how long an enqueue + dequeue of a single item
88  * takes on a single lcore. Result is for comparison with the bulk enq+deq.
89  */
90 static void
91 test_single_enqueue_dequeue(void)
92 {
93         const unsigned iter_shift = 24;
94         const unsigned iterations = 1 << iter_shift;
95         unsigned i = 0;
96         void *burst = NULL;
97         struct rte_mbuf *mburst[1] = { NULL };
98
99         const uint64_t sc_start = rte_rdtsc_precise();
100         rte_compiler_barrier();
101         for (i = 0; i < iterations; i++) {
102                 rte_ring_enqueue_bulk(r, &burst, 1, NULL);
103                 rte_ring_dequeue_bulk(r, &burst, 1, NULL);
104         }
105         const uint64_t sc_end = rte_rdtsc_precise();
106         rte_compiler_barrier();
107
108         const uint64_t eth_start = rte_rdtsc_precise();
109         rte_compiler_barrier();
110         for (i = 0; i < iterations; i++) {
111                 rte_eth_tx_burst(ring_ethdev_port, 0, mburst, 1);
112                 rte_eth_rx_burst(ring_ethdev_port, 0, mburst, 1);
113         }
114         const uint64_t eth_end = rte_rdtsc_precise();
115         rte_compiler_barrier();
116
117         printf("Ring single enq/dequeue  : %"PRIu64"\n",
118                         (sc_end-sc_start) >> iter_shift);
119         printf("Ethdev single enq/dequeue: %"PRIu64"\n",
120                         (eth_end-eth_start) >> iter_shift);
121 }
122
123 /* Times enqueue and dequeue on a single lcore */
124 static void
125 test_bulk_enqueue_dequeue(void)
126 {
127         const unsigned iter_shift = 23;
128         const unsigned iterations = 1 << iter_shift;
129         unsigned sz, i = 0;
130         struct rte_mbuf *burst[MAX_BURST] = {0};
131
132         for (sz = 0; sz < sizeof(bulk_sizes)/sizeof(bulk_sizes[0]); sz++) {
133                 const uint64_t sc_start = rte_rdtsc();
134                 for (i = 0; i < iterations; i++) {
135                         rte_ring_sp_enqueue_bulk(r, (void *)burst,
136                                         bulk_sizes[sz], NULL);
137                         rte_ring_sc_dequeue_bulk(r, (void *)burst,
138                                         bulk_sizes[sz], NULL);
139                 }
140                 const uint64_t sc_end = rte_rdtsc();
141
142                 const uint64_t eth_start = rte_rdtsc_precise();
143                 rte_compiler_barrier();
144                 for (i = 0; i < iterations; i++) {
145                         rte_eth_tx_burst(ring_ethdev_port, 0, burst, bulk_sizes[sz]);
146                         rte_eth_rx_burst(ring_ethdev_port, 0, burst, bulk_sizes[sz]);
147                 }
148                 const uint64_t eth_end = rte_rdtsc_precise();
149                 rte_compiler_barrier();
150
151                 double sc_avg = ((double)(sc_end-sc_start) /
152                                 (iterations * bulk_sizes[sz]));
153                 double eth_avg = ((double)(eth_end-eth_start) /
154                                 (iterations * bulk_sizes[sz]));
155
156                 printf("ring bulk enq/deq (size: %u) : %.1F\n", bulk_sizes[sz],
157                                 sc_avg);
158                 printf("ethdev bulk enq/deq (size:%u): %.1F\n", bulk_sizes[sz],
159                                 eth_avg);
160
161                 printf("\n");
162         }
163 }
164
165 static int
166 test_ring_pmd_perf(void)
167 {
168         char name[RTE_ETH_NAME_MAX_LEN];
169
170         r = rte_ring_create(RING_NAME, RING_SIZE, rte_socket_id(),
171                         RING_F_SP_ENQ|RING_F_SC_DEQ);
172         if (r == NULL && (r = rte_ring_lookup(RING_NAME)) == NULL)
173                 return -1;
174
175         ring_ethdev_port = rte_eth_from_ring(r);
176
177         printf("\n### Testing const single element enq/deq ###\n");
178         test_single_enqueue_dequeue();
179
180         printf("\n### Testing empty dequeue ###\n");
181         test_empty_dequeue();
182
183         printf("\n### Testing using a single lcore ###\n");
184         test_bulk_enqueue_dequeue();
185
186         /* release port and ring resources */
187         rte_eth_dev_stop(ring_ethdev_port);
188         rte_eth_dev_get_name_by_port(ring_ethdev_port, name);
189         rte_vdev_uninit(name);
190         rte_ring_free(r);
191         return 0;
192 }
193
194 REGISTER_TEST_COMMAND(ring_pmd_perf_autotest, test_ring_pmd_perf);