xref: /dpdk/app/test/test_ring_perf.c (revision a4cb5461cf0edc92cc63e6122edfa9c974e78e46)
1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3759cf9b5SJoyce Kong  * Copyright(c) 2019 Arm Limited
4a9de470cSBruce Richardson  */
5a9de470cSBruce Richardson 
6a9de470cSBruce Richardson 
7a9de470cSBruce Richardson #include <stdio.h>
8a9de470cSBruce Richardson #include <inttypes.h>
9a9de470cSBruce Richardson #include <rte_ring.h>
10a9de470cSBruce Richardson #include <rte_cycles.h>
11a9de470cSBruce Richardson #include <rte_launch.h>
12a9de470cSBruce Richardson #include <rte_pause.h>
13759cf9b5SJoyce Kong #include <string.h>
14a9de470cSBruce Richardson 
15a9de470cSBruce Richardson #include "test.h"
161fa5d009SHonnappa Nagarahalli #include "test_ring.h"
17a9de470cSBruce Richardson 
18a9de470cSBruce Richardson /*
191fa5d009SHonnappa Nagarahalli  * Ring performance test cases, measures performance of various operations
201fa5d009SHonnappa Nagarahalli  * using rdtsc for legacy and 16B size ring elements.
21a9de470cSBruce Richardson  */
22a9de470cSBruce Richardson 
23a9de470cSBruce Richardson #define RING_NAME "RING_PERF"
24a9de470cSBruce Richardson #define RING_SIZE 4096
25*a4cb5461SPaul Szczepanek #define MAX_BURST 256
26a9de470cSBruce Richardson 
27a9de470cSBruce Richardson /*
28a9de470cSBruce Richardson  * the sizes to enqueue and dequeue in testing
29a9de470cSBruce Richardson  * (marked volatile so they won't be seen as compile-time constants)
30a9de470cSBruce Richardson  */
31*a4cb5461SPaul Szczepanek static const volatile unsigned int bulk_sizes[] = { 8, 32, 64, 128, 256 };
32a9de470cSBruce Richardson 
33a9de470cSBruce Richardson struct lcore_pair {
34a9de470cSBruce Richardson 	unsigned c1, c2;
35a9de470cSBruce Richardson };
36a9de470cSBruce Richardson 
37a9de470cSBruce Richardson static volatile unsigned lcore_count = 0;
38a9de470cSBruce Richardson 
391fa5d009SHonnappa Nagarahalli static void
test_ring_print_test_string(unsigned int api_type,int esize,unsigned int bsz,double value)401fa5d009SHonnappa Nagarahalli test_ring_print_test_string(unsigned int api_type, int esize,
411fa5d009SHonnappa Nagarahalli 	unsigned int bsz, double value)
421fa5d009SHonnappa Nagarahalli {
431fa5d009SHonnappa Nagarahalli 	if (esize == -1)
441fa5d009SHonnappa Nagarahalli 		printf("legacy APIs");
451fa5d009SHonnappa Nagarahalli 	else
46*a4cb5461SPaul Szczepanek 		printf("elem APIs (size:%2dB)", esize);
471fa5d009SHonnappa Nagarahalli 
481fa5d009SHonnappa Nagarahalli 	if (api_type == TEST_RING_IGNORE_API_TYPE)
491fa5d009SHonnappa Nagarahalli 		return;
501fa5d009SHonnappa Nagarahalli 
511fa5d009SHonnappa Nagarahalli 	if ((api_type & TEST_RING_THREAD_DEF) == TEST_RING_THREAD_DEF)
52*a4cb5461SPaul Szczepanek 		printf(" - default enqueue/dequeue");
531fa5d009SHonnappa Nagarahalli 	else if ((api_type & TEST_RING_THREAD_SPSC) == TEST_RING_THREAD_SPSC)
54*a4cb5461SPaul Szczepanek 		printf(" - SP/SC");
551fa5d009SHonnappa Nagarahalli 	else if ((api_type & TEST_RING_THREAD_MPMC) == TEST_RING_THREAD_MPMC)
56*a4cb5461SPaul Szczepanek 		printf(" - MP/MC");
571fa5d009SHonnappa Nagarahalli 
581fa5d009SHonnappa Nagarahalli 	if ((api_type & TEST_RING_ELEM_SINGLE) == TEST_RING_ELEM_SINGLE)
59*a4cb5461SPaul Szczepanek 		printf(" - single - ");
601fa5d009SHonnappa Nagarahalli 	else if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
61*a4cb5461SPaul Szczepanek 		printf(" - bulk (n:%-3u) - ", bsz);
621fa5d009SHonnappa Nagarahalli 	else if ((api_type & TEST_RING_ELEM_BURST) == TEST_RING_ELEM_BURST)
63*a4cb5461SPaul Szczepanek 		printf(" - burst (n:%-3u) - ", bsz);
64*a4cb5461SPaul Szczepanek 	else if ((api_type & (TEST_RING_ELEM_BURST_ZC |
65*a4cb5461SPaul Szczepanek 			TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_16 |
66*a4cb5461SPaul Szczepanek 			TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_32)) != 0)
67*a4cb5461SPaul Szczepanek 		printf(" - burst zero copy (n:%-3u) - ", bsz);
681fa5d009SHonnappa Nagarahalli 
69*a4cb5461SPaul Szczepanek 	printf("cycles per elem: %.3F\n", value);
701fa5d009SHonnappa Nagarahalli }
711fa5d009SHonnappa Nagarahalli 
72a9de470cSBruce Richardson /**** Functions to analyse our core mask to get cores for different tests ***/
73a9de470cSBruce Richardson 
74a9de470cSBruce Richardson static int
get_two_hyperthreads(struct lcore_pair * lcp)75a9de470cSBruce Richardson get_two_hyperthreads(struct lcore_pair *lcp)
76a9de470cSBruce Richardson {
77a9de470cSBruce Richardson 	unsigned id1, id2;
78a9de470cSBruce Richardson 	unsigned c1, c2, s1, s2;
79a9de470cSBruce Richardson 	RTE_LCORE_FOREACH(id1) {
80a9de470cSBruce Richardson 		/* inner loop just re-reads all id's. We could skip the first few
81a9de470cSBruce Richardson 		 * elements, but since number of cores is small there is little point
82a9de470cSBruce Richardson 		 */
83a9de470cSBruce Richardson 		RTE_LCORE_FOREACH(id2) {
84a9de470cSBruce Richardson 			if (id1 == id2)
85a9de470cSBruce Richardson 				continue;
86de307f7aSStephen Hemminger 
87de307f7aSStephen Hemminger 			c1 = rte_lcore_to_cpu_id(id1);
88de307f7aSStephen Hemminger 			c2 = rte_lcore_to_cpu_id(id2);
89de307f7aSStephen Hemminger 			s1 = rte_lcore_to_socket_id(id1);
90de307f7aSStephen Hemminger 			s2 = rte_lcore_to_socket_id(id2);
91a9de470cSBruce Richardson 			if ((c1 == c2) && (s1 == s2)){
92a9de470cSBruce Richardson 				lcp->c1 = id1;
93a9de470cSBruce Richardson 				lcp->c2 = id2;
94a9de470cSBruce Richardson 				return 0;
95a9de470cSBruce Richardson 			}
96a9de470cSBruce Richardson 		}
97a9de470cSBruce Richardson 	}
98a9de470cSBruce Richardson 	return 1;
99a9de470cSBruce Richardson }
100a9de470cSBruce Richardson 
101a9de470cSBruce Richardson static int
get_two_cores(struct lcore_pair * lcp)102a9de470cSBruce Richardson get_two_cores(struct lcore_pair *lcp)
103a9de470cSBruce Richardson {
104a9de470cSBruce Richardson 	unsigned id1, id2;
105a9de470cSBruce Richardson 	unsigned c1, c2, s1, s2;
106a9de470cSBruce Richardson 	RTE_LCORE_FOREACH(id1) {
107a9de470cSBruce Richardson 		RTE_LCORE_FOREACH(id2) {
108a9de470cSBruce Richardson 			if (id1 == id2)
109a9de470cSBruce Richardson 				continue;
110de307f7aSStephen Hemminger 
111de307f7aSStephen Hemminger 			c1 = rte_lcore_to_cpu_id(id1);
112de307f7aSStephen Hemminger 			c2 = rte_lcore_to_cpu_id(id2);
113de307f7aSStephen Hemminger 			s1 = rte_lcore_to_socket_id(id1);
114de307f7aSStephen Hemminger 			s2 = rte_lcore_to_socket_id(id2);
115a9de470cSBruce Richardson 			if ((c1 != c2) && (s1 == s2)){
116a9de470cSBruce Richardson 				lcp->c1 = id1;
117a9de470cSBruce Richardson 				lcp->c2 = id2;
118a9de470cSBruce Richardson 				return 0;
119a9de470cSBruce Richardson 			}
120a9de470cSBruce Richardson 		}
121a9de470cSBruce Richardson 	}
122a9de470cSBruce Richardson 	return 1;
123a9de470cSBruce Richardson }
124a9de470cSBruce Richardson 
125a9de470cSBruce Richardson static int
get_two_sockets(struct lcore_pair * lcp)126a9de470cSBruce Richardson get_two_sockets(struct lcore_pair *lcp)
127a9de470cSBruce Richardson {
128a9de470cSBruce Richardson 	unsigned id1, id2;
129a9de470cSBruce Richardson 	unsigned s1, s2;
130a9de470cSBruce Richardson 	RTE_LCORE_FOREACH(id1) {
131a9de470cSBruce Richardson 		RTE_LCORE_FOREACH(id2) {
132a9de470cSBruce Richardson 			if (id1 == id2)
133a9de470cSBruce Richardson 				continue;
134de307f7aSStephen Hemminger 			s1 = rte_lcore_to_socket_id(id1);
135de307f7aSStephen Hemminger 			s2 = rte_lcore_to_socket_id(id2);
136a9de470cSBruce Richardson 			if (s1 != s2){
137a9de470cSBruce Richardson 				lcp->c1 = id1;
138a9de470cSBruce Richardson 				lcp->c2 = id2;
139a9de470cSBruce Richardson 				return 0;
140a9de470cSBruce Richardson 			}
141a9de470cSBruce Richardson 		}
142a9de470cSBruce Richardson 	}
143a9de470cSBruce Richardson 	return 1;
144a9de470cSBruce Richardson }
145a9de470cSBruce Richardson 
146a9de470cSBruce Richardson /* Get cycle counts for dequeuing from an empty ring. Should be 2 or 3 cycles */
147a9de470cSBruce Richardson static void
test_empty_dequeue(struct rte_ring * r,const int esize,const unsigned int api_type)1481fa5d009SHonnappa Nagarahalli test_empty_dequeue(struct rte_ring *r, const int esize,
1491fa5d009SHonnappa Nagarahalli 			const unsigned int api_type)
150a9de470cSBruce Richardson {
151*a4cb5461SPaul Szczepanek 	const unsigned int iter_shift = 29;
1521fa5d009SHonnappa Nagarahalli 	const unsigned int iterations = 1 << iter_shift;
1531fa5d009SHonnappa Nagarahalli 	unsigned int i = 0;
154a9de470cSBruce Richardson 	void *burst[MAX_BURST];
155a9de470cSBruce Richardson 
156*a4cb5461SPaul Szczepanek 	const unsigned int bulk_iterations = iterations / bulk_sizes[0];
1571fa5d009SHonnappa Nagarahalli 	const uint64_t start = rte_rdtsc();
158*a4cb5461SPaul Szczepanek 	for (i = 0; i < bulk_iterations; i++)
1591fa5d009SHonnappa Nagarahalli 		test_ring_dequeue(r, burst, esize, bulk_sizes[0], api_type);
1601fa5d009SHonnappa Nagarahalli 	const uint64_t end = rte_rdtsc();
161a9de470cSBruce Richardson 
1621fa5d009SHonnappa Nagarahalli 	test_ring_print_test_string(api_type, esize, bulk_sizes[0],
163*a4cb5461SPaul Szczepanek 					((double)end - start) / iterations);
164a9de470cSBruce Richardson }
165a9de470cSBruce Richardson 
166*a4cb5461SPaul Szczepanek /* describes the ring used by the enqueue and dequeue thread */
167*a4cb5461SPaul Szczepanek struct ring_params {
168a9de470cSBruce Richardson 	struct rte_ring *r;
169*a4cb5461SPaul Szczepanek 	unsigned int elem_size;
170*a4cb5461SPaul Szczepanek 	unsigned int bulk_sizes_i; /* index into bulk_size array */
171*a4cb5461SPaul Szczepanek 	unsigned int ring_flags; /* flags for test_ring_enqueue/dequeue */
172*a4cb5461SPaul Szczepanek };
173*a4cb5461SPaul Szczepanek 
174*a4cb5461SPaul Szczepanek /* Used to specify enqueue and dequeue ring operations and their results */
175*a4cb5461SPaul Szczepanek struct thread_params {
176*a4cb5461SPaul Szczepanek 	struct ring_params *ring_params;
177*a4cb5461SPaul Szczepanek 	double *results; /* result array size must be equal to bulk_sizes */
178a9de470cSBruce Richardson };
179a9de470cSBruce Richardson 
180a9de470cSBruce Richardson /*
1811fa5d009SHonnappa Nagarahalli  * Helper function to call bulk SP/MP enqueue functions.
1821fa5d009SHonnappa Nagarahalli  * flag == 0 -> enqueue
1831fa5d009SHonnappa Nagarahalli  * flag == 1 -> dequeue
184a9de470cSBruce Richardson  */
1851fa5d009SHonnappa Nagarahalli static __rte_always_inline int
enqueue_dequeue_bulk_helper(const unsigned int flag,struct thread_params * p)186*a4cb5461SPaul Szczepanek enqueue_dequeue_bulk_helper(const unsigned int flag, struct thread_params *p)
187a9de470cSBruce Richardson {
1881fa5d009SHonnappa Nagarahalli 	int ret;
189*a4cb5461SPaul Szczepanek 	const unsigned int iter_shift = 22;
1901fa5d009SHonnappa Nagarahalli 	const unsigned int iterations = 1 << iter_shift;
1911fa5d009SHonnappa Nagarahalli 	unsigned int i;
1921fa5d009SHonnappa Nagarahalli 	void *burst = NULL;
193*a4cb5461SPaul Szczepanek 	unsigned int n_remaining;
194*a4cb5461SPaul Szczepanek 	const unsigned int bulk_n = bulk_sizes[p->ring_params->bulk_sizes_i];
195a9de470cSBruce Richardson 
196e4eb7b06SPhil Yang #ifdef RTE_USE_C11_MEM_MODEL
197b6a7e685STyler Retzlaff 	if (rte_atomic_fetch_add_explicit(&lcore_count, 1, rte_memory_order_relaxed) + 1 != 2)
198e4eb7b06SPhil Yang #else
199a9de470cSBruce Richardson 	if (__sync_add_and_fetch(&lcore_count, 1) != 2)
200e4eb7b06SPhil Yang #endif
201a9de470cSBruce Richardson 		while(lcore_count != 2)
202a9de470cSBruce Richardson 			rte_pause();
203a9de470cSBruce Richardson 
204*a4cb5461SPaul Szczepanek 	burst = test_ring_calloc(MAX_BURST, p->ring_params->elem_size);
2051fa5d009SHonnappa Nagarahalli 	if (burst == NULL)
2061fa5d009SHonnappa Nagarahalli 		return -1;
2071fa5d009SHonnappa Nagarahalli 
208a9de470cSBruce Richardson 	const uint64_t sp_start = rte_rdtsc();
209*a4cb5461SPaul Szczepanek 	const unsigned int bulk_iterations = iterations / bulk_n;
210*a4cb5461SPaul Szczepanek 	for (i = 0; i < bulk_iterations; i++) {
211*a4cb5461SPaul Szczepanek 		n_remaining = bulk_n;
2121fa5d009SHonnappa Nagarahalli 		do {
2131fa5d009SHonnappa Nagarahalli 			if (flag == 0)
214*a4cb5461SPaul Szczepanek 				ret = test_ring_enqueue(p->ring_params->r,
215*a4cb5461SPaul Szczepanek 						burst,
216*a4cb5461SPaul Szczepanek 						p->ring_params->elem_size,
217*a4cb5461SPaul Szczepanek 						n_remaining,
218*a4cb5461SPaul Szczepanek 						p->ring_params->ring_flags);
2191fa5d009SHonnappa Nagarahalli 			else if (flag == 1)
220*a4cb5461SPaul Szczepanek 				ret = test_ring_dequeue(p->ring_params->r,
221*a4cb5461SPaul Szczepanek 						burst,
222*a4cb5461SPaul Szczepanek 						p->ring_params->elem_size,
223*a4cb5461SPaul Szczepanek 						n_remaining,
224*a4cb5461SPaul Szczepanek 						p->ring_params->ring_flags);
2251fa5d009SHonnappa Nagarahalli 			if (ret == 0)
226a9de470cSBruce Richardson 				rte_pause();
227*a4cb5461SPaul Szczepanek 			else
228*a4cb5461SPaul Szczepanek 				n_remaining -= ret;
229*a4cb5461SPaul Szczepanek 		} while (n_remaining > 0);
230*a4cb5461SPaul Szczepanek 	}
231a9de470cSBruce Richardson 	const uint64_t sp_end = rte_rdtsc();
232a9de470cSBruce Richardson 
233*a4cb5461SPaul Szczepanek 	p->results[p->ring_params->bulk_sizes_i] =
234*a4cb5461SPaul Szczepanek 			((double)sp_end - sp_start) / iterations;
235a9de470cSBruce Richardson 
236a9de470cSBruce Richardson 	return 0;
237a9de470cSBruce Richardson }
238a9de470cSBruce Richardson 
239a9de470cSBruce Richardson /*
2401fa5d009SHonnappa Nagarahalli  * Function that uses rdtsc to measure timing for ring enqueue. Needs pair
2411fa5d009SHonnappa Nagarahalli  * thread running dequeue_bulk function
2421fa5d009SHonnappa Nagarahalli  */
2431fa5d009SHonnappa Nagarahalli static int
enqueue_bulk(void * p)2441fa5d009SHonnappa Nagarahalli enqueue_bulk(void *p)
2451fa5d009SHonnappa Nagarahalli {
2461fa5d009SHonnappa Nagarahalli 	struct thread_params *params = p;
2471fa5d009SHonnappa Nagarahalli 
248*a4cb5461SPaul Szczepanek 	return enqueue_dequeue_bulk_helper(0, params);
2491fa5d009SHonnappa Nagarahalli }
2501fa5d009SHonnappa Nagarahalli 
2511fa5d009SHonnappa Nagarahalli /*
252a9de470cSBruce Richardson  * Function that uses rdtsc to measure timing for ring dequeue. Needs pair
253a9de470cSBruce Richardson  * thread running enqueue_bulk function
254a9de470cSBruce Richardson  */
255a9de470cSBruce Richardson static int
dequeue_bulk(void * p)256a9de470cSBruce Richardson dequeue_bulk(void *p)
257a9de470cSBruce Richardson {
258a9de470cSBruce Richardson 	struct thread_params *params = p;
259a9de470cSBruce Richardson 
260*a4cb5461SPaul Szczepanek 	return enqueue_dequeue_bulk_helper(1, params);
261a9de470cSBruce Richardson }
262a9de470cSBruce Richardson 
263a9de470cSBruce Richardson /*
264a9de470cSBruce Richardson  * Function that calls the enqueue and dequeue bulk functions on pairs of cores.
265a9de470cSBruce Richardson  * used to measure ring perf between hyperthreads, cores and sockets.
266a9de470cSBruce Richardson  */
2671fa5d009SHonnappa Nagarahalli static int
run_on_core_pair(struct lcore_pair * cores,struct thread_params * param1,struct thread_params * param2)268*a4cb5461SPaul Szczepanek run_on_core_pair(struct lcore_pair *cores,
269*a4cb5461SPaul Szczepanek 		struct thread_params *param1, struct thread_params *param2)
270a9de470cSBruce Richardson {
271a9de470cSBruce Richardson 	unsigned i;
272*a4cb5461SPaul Szczepanek 	struct ring_params *ring_params = param1->ring_params;
2731fa5d009SHonnappa Nagarahalli 
27471bdd8a1SPavan Nikhilesh 	for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
275a9de470cSBruce Richardson 		lcore_count = 0;
276*a4cb5461SPaul Szczepanek 		ring_params->bulk_sizes_i = i;
277cb056611SStephen Hemminger 		if (cores->c1 == rte_get_main_lcore()) {
278*a4cb5461SPaul Szczepanek 			rte_eal_remote_launch(dequeue_bulk, param2, cores->c2);
279*a4cb5461SPaul Szczepanek 			enqueue_bulk(param1);
280a9de470cSBruce Richardson 			rte_eal_wait_lcore(cores->c2);
281a9de470cSBruce Richardson 		} else {
282*a4cb5461SPaul Szczepanek 			rte_eal_remote_launch(enqueue_bulk, param1, cores->c1);
283*a4cb5461SPaul Szczepanek 			rte_eal_remote_launch(dequeue_bulk, param2, cores->c2);
2841fa5d009SHonnappa Nagarahalli 			if (rte_eal_wait_lcore(cores->c1) < 0)
2851fa5d009SHonnappa Nagarahalli 				return -1;
2861fa5d009SHonnappa Nagarahalli 			if (rte_eal_wait_lcore(cores->c2) < 0)
2871fa5d009SHonnappa Nagarahalli 				return -1;
288a9de470cSBruce Richardson 		}
2891fa5d009SHonnappa Nagarahalli 		test_ring_print_test_string(
290*a4cb5461SPaul Szczepanek 				ring_params->ring_flags,
291*a4cb5461SPaul Szczepanek 				ring_params->elem_size,
292*a4cb5461SPaul Szczepanek 				bulk_sizes[i],
293*a4cb5461SPaul Szczepanek 				param1->results[i] + param2->results[i]);
294a9de470cSBruce Richardson 	}
2951fa5d009SHonnappa Nagarahalli 
2961fa5d009SHonnappa Nagarahalli 	return 0;
297a9de470cSBruce Richardson }
298a9de470cSBruce Richardson 
299b6a7e685STyler Retzlaff static RTE_ATOMIC(uint32_t) synchro;
300759cf9b5SJoyce Kong static uint64_t queue_count[RTE_MAX_LCORE];
301759cf9b5SJoyce Kong 
302759cf9b5SJoyce Kong #define TIME_MS 100
303759cf9b5SJoyce Kong 
304759cf9b5SJoyce Kong static int
load_loop_fn_helper(struct thread_params * p,const int esize)3051fa5d009SHonnappa Nagarahalli load_loop_fn_helper(struct thread_params *p, const int esize)
306759cf9b5SJoyce Kong {
307759cf9b5SJoyce Kong 	uint64_t time_diff = 0;
308759cf9b5SJoyce Kong 	uint64_t begin = 0;
309759cf9b5SJoyce Kong 	uint64_t hz = rte_get_timer_hz();
310759cf9b5SJoyce Kong 	uint64_t lcount = 0;
311759cf9b5SJoyce Kong 	const unsigned int lcore = rte_lcore_id();
312*a4cb5461SPaul Szczepanek 	struct ring_params *ring_params = p->ring_params;
3131fa5d009SHonnappa Nagarahalli 	void *burst = NULL;
3141fa5d009SHonnappa Nagarahalli 
3151fa5d009SHonnappa Nagarahalli 	burst = test_ring_calloc(MAX_BURST, esize);
3161fa5d009SHonnappa Nagarahalli 	if (burst == NULL)
3171fa5d009SHonnappa Nagarahalli 		return -1;
318759cf9b5SJoyce Kong 
319cb056611SStephen Hemminger 	/* wait synchro for workers */
320cb056611SStephen Hemminger 	if (lcore != rte_get_main_lcore())
321b6a7e685STyler Retzlaff 		rte_wait_until_equal_32((uint32_t *)(uintptr_t)&synchro, 1,
322b6a7e685STyler Retzlaff 				rte_memory_order_relaxed);
323759cf9b5SJoyce Kong 
324759cf9b5SJoyce Kong 	begin = rte_get_timer_cycles();
325759cf9b5SJoyce Kong 	while (time_diff < hz * TIME_MS / 1000) {
326*a4cb5461SPaul Szczepanek 		test_ring_enqueue(ring_params->r, burst, esize,
327*a4cb5461SPaul Szczepanek 				ring_params->elem_size,
3281fa5d009SHonnappa Nagarahalli 				TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
329*a4cb5461SPaul Szczepanek 		test_ring_dequeue(ring_params->r, burst, esize,
330*a4cb5461SPaul Szczepanek 				ring_params->elem_size,
3311fa5d009SHonnappa Nagarahalli 				TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
332759cf9b5SJoyce Kong 		lcount++;
333759cf9b5SJoyce Kong 		time_diff = rte_get_timer_cycles() - begin;
334759cf9b5SJoyce Kong 	}
335759cf9b5SJoyce Kong 	queue_count[lcore] = lcount;
3361fa5d009SHonnappa Nagarahalli 
3371fa5d009SHonnappa Nagarahalli 	rte_free(burst);
3381fa5d009SHonnappa Nagarahalli 
339759cf9b5SJoyce Kong 	return 0;
340759cf9b5SJoyce Kong }
341759cf9b5SJoyce Kong 
342759cf9b5SJoyce Kong static int
load_loop_fn(void * p)3431fa5d009SHonnappa Nagarahalli load_loop_fn(void *p)
3441fa5d009SHonnappa Nagarahalli {
3451fa5d009SHonnappa Nagarahalli 	struct thread_params *params = p;
3461fa5d009SHonnappa Nagarahalli 
3471fa5d009SHonnappa Nagarahalli 	return load_loop_fn_helper(params, -1);
3481fa5d009SHonnappa Nagarahalli }
3491fa5d009SHonnappa Nagarahalli 
3501fa5d009SHonnappa Nagarahalli static int
load_loop_fn_16B(void * p)3511fa5d009SHonnappa Nagarahalli load_loop_fn_16B(void *p)
3521fa5d009SHonnappa Nagarahalli {
3531fa5d009SHonnappa Nagarahalli 	struct thread_params *params = p;
3541fa5d009SHonnappa Nagarahalli 
3551fa5d009SHonnappa Nagarahalli 	return load_loop_fn_helper(params, 16);
3561fa5d009SHonnappa Nagarahalli }
3571fa5d009SHonnappa Nagarahalli 
3581fa5d009SHonnappa Nagarahalli static int
run_on_all_cores(struct rte_ring * r,const int esize)3591fa5d009SHonnappa Nagarahalli run_on_all_cores(struct rte_ring *r, const int esize)
360759cf9b5SJoyce Kong {
36150959a89SFeifei Wang 	uint64_t total;
362*a4cb5461SPaul Szczepanek 	struct ring_params ring_params = {0};
363*a4cb5461SPaul Szczepanek 	struct thread_params params = { .ring_params = &ring_params };
3641fa5d009SHonnappa Nagarahalli 	lcore_function_t *lcore_f;
365759cf9b5SJoyce Kong 	unsigned int i, c;
366759cf9b5SJoyce Kong 
3671fa5d009SHonnappa Nagarahalli 	if (esize == -1)
3681fa5d009SHonnappa Nagarahalli 		lcore_f = load_loop_fn;
3691fa5d009SHonnappa Nagarahalli 	else
3701fa5d009SHonnappa Nagarahalli 		lcore_f = load_loop_fn_16B;
3711fa5d009SHonnappa Nagarahalli 
372759cf9b5SJoyce Kong 	for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
37350959a89SFeifei Wang 		total = 0;
374759cf9b5SJoyce Kong 		printf("\nBulk enq/dequeue count on size %u\n", bulk_sizes[i]);
375*a4cb5461SPaul Szczepanek 		params.ring_params->bulk_sizes_i = i;
376*a4cb5461SPaul Szczepanek 		params.ring_params->r = r;
377759cf9b5SJoyce Kong 
378cb056611SStephen Hemminger 		/* clear synchro and start workers */
379b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&synchro, 0, rte_memory_order_relaxed);
380*a4cb5461SPaul Szczepanek 		if (rte_eal_mp_remote_launch(lcore_f, &params, SKIP_MAIN) < 0)
381759cf9b5SJoyce Kong 			return -1;
382759cf9b5SJoyce Kong 
383cb056611SStephen Hemminger 		/* start synchro and launch test on main */
384b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&synchro, 1, rte_memory_order_relaxed);
385*a4cb5461SPaul Szczepanek 		lcore_f(&params);
386759cf9b5SJoyce Kong 
387759cf9b5SJoyce Kong 		rte_eal_mp_wait_lcore();
388759cf9b5SJoyce Kong 
389759cf9b5SJoyce Kong 		RTE_LCORE_FOREACH(c) {
390759cf9b5SJoyce Kong 			printf("Core [%u] count = %"PRIu64"\n",
391759cf9b5SJoyce Kong 					c, queue_count[c]);
392759cf9b5SJoyce Kong 			total += queue_count[c];
393759cf9b5SJoyce Kong 		}
394759cf9b5SJoyce Kong 
395759cf9b5SJoyce Kong 		printf("Total count (size: %u): %"PRIu64"\n",
396759cf9b5SJoyce Kong 				bulk_sizes[i], total);
397759cf9b5SJoyce Kong 	}
398759cf9b5SJoyce Kong 
399759cf9b5SJoyce Kong 	return 0;
400759cf9b5SJoyce Kong }
401759cf9b5SJoyce Kong 
402a9de470cSBruce Richardson /*
403a9de470cSBruce Richardson  * Test function that determines how long an enqueue + dequeue of a single item
404a9de470cSBruce Richardson  * takes on a single lcore. Result is for comparison with the bulk enq+deq.
405a9de470cSBruce Richardson  */
4061fa5d009SHonnappa Nagarahalli static int
test_single_enqueue_dequeue(struct rte_ring * r,const int esize,const unsigned int api_type)4071fa5d009SHonnappa Nagarahalli test_single_enqueue_dequeue(struct rte_ring *r, const int esize,
4081fa5d009SHonnappa Nagarahalli 	const unsigned int api_type)
409a9de470cSBruce Richardson {
4101fa5d009SHonnappa Nagarahalli 	const unsigned int iter_shift = 24;
4111fa5d009SHonnappa Nagarahalli 	const unsigned int iterations = 1 << iter_shift;
4121fa5d009SHonnappa Nagarahalli 	unsigned int i = 0;
413a9de470cSBruce Richardson 	void *burst = NULL;
414a9de470cSBruce Richardson 
4151fa5d009SHonnappa Nagarahalli 	/* alloc dummy object pointers */
4161fa5d009SHonnappa Nagarahalli 	burst = test_ring_calloc(1, esize);
4171fa5d009SHonnappa Nagarahalli 	if (burst == NULL)
4181fa5d009SHonnappa Nagarahalli 		return -1;
419a9de470cSBruce Richardson 
4201fa5d009SHonnappa Nagarahalli 	const uint64_t start = rte_rdtsc();
421a9de470cSBruce Richardson 	for (i = 0; i < iterations; i++) {
4221fa5d009SHonnappa Nagarahalli 		test_ring_enqueue(r, burst, esize, 1, api_type);
4231fa5d009SHonnappa Nagarahalli 		test_ring_dequeue(r, burst, esize, 1, api_type);
424a9de470cSBruce Richardson 	}
4251fa5d009SHonnappa Nagarahalli 	const uint64_t end = rte_rdtsc();
426a9de470cSBruce Richardson 
4271fa5d009SHonnappa Nagarahalli 	test_ring_print_test_string(api_type, esize, 1,
4281fa5d009SHonnappa Nagarahalli 					((double)(end - start)) / iterations);
4291fa5d009SHonnappa Nagarahalli 
4301fa5d009SHonnappa Nagarahalli 	rte_free(burst);
4311fa5d009SHonnappa Nagarahalli 
4321fa5d009SHonnappa Nagarahalli 	return 0;
433a9de470cSBruce Richardson }
434a9de470cSBruce Richardson 
435a9de470cSBruce Richardson /*
4361fa5d009SHonnappa Nagarahalli  * Test that does both enqueue and dequeue on a core using the burst/bulk API
4371fa5d009SHonnappa Nagarahalli  * calls Results should be the same as for the bulk function called on a
4381fa5d009SHonnappa Nagarahalli  * single lcore.
439a9de470cSBruce Richardson  */
4401fa5d009SHonnappa Nagarahalli static int
test_burst_bulk_enqueue_dequeue(struct rte_ring * r,const int esize,const unsigned int api_type)4411fa5d009SHonnappa Nagarahalli test_burst_bulk_enqueue_dequeue(struct rte_ring *r, const int esize,
4421fa5d009SHonnappa Nagarahalli 	const unsigned int api_type)
443a9de470cSBruce Richardson {
444*a4cb5461SPaul Szczepanek 	const unsigned int iter_shift = 26;
4451fa5d009SHonnappa Nagarahalli 	const unsigned int iterations = 1 << iter_shift;
446*a4cb5461SPaul Szczepanek 	unsigned int sz, i;
4471fa5d009SHonnappa Nagarahalli 	void **burst = NULL;
448a9de470cSBruce Richardson 
4491fa5d009SHonnappa Nagarahalli 	burst = test_ring_calloc(MAX_BURST, esize);
4501fa5d009SHonnappa Nagarahalli 	if (burst == NULL)
4511fa5d009SHonnappa Nagarahalli 		return -1;
4521fa5d009SHonnappa Nagarahalli 
4531fa5d009SHonnappa Nagarahalli 	for (sz = 0; sz < RTE_DIM(bulk_sizes); sz++) {
454*a4cb5461SPaul Szczepanek 		const unsigned int n = iterations / bulk_sizes[sz];
4551fa5d009SHonnappa Nagarahalli 		const uint64_t start = rte_rdtsc();
456*a4cb5461SPaul Szczepanek 		for (i = 0; i < n; i++) {
4571fa5d009SHonnappa Nagarahalli 			test_ring_enqueue(r, burst, esize, bulk_sizes[sz],
4581fa5d009SHonnappa Nagarahalli 					api_type);
4591fa5d009SHonnappa Nagarahalli 			test_ring_dequeue(r, burst, esize, bulk_sizes[sz],
4601fa5d009SHonnappa Nagarahalli 					api_type);
461a9de470cSBruce Richardson 		}
4621fa5d009SHonnappa Nagarahalli 		const uint64_t end = rte_rdtsc();
463a9de470cSBruce Richardson 
4641fa5d009SHonnappa Nagarahalli 		test_ring_print_test_string(api_type, esize, bulk_sizes[sz],
465*a4cb5461SPaul Szczepanek 					((double)end - start) / iterations);
466a9de470cSBruce Richardson 	}
467a9de470cSBruce Richardson 
4681fa5d009SHonnappa Nagarahalli 	rte_free(burst);
4691fa5d009SHonnappa Nagarahalli 
4701fa5d009SHonnappa Nagarahalli 	return 0;
4711fa5d009SHonnappa Nagarahalli }
4721fa5d009SHonnappa Nagarahalli 
473*a4cb5461SPaul Szczepanek static __rte_always_inline int
test_ring_perf_esize_run_on_two_cores(struct thread_params * param1,struct thread_params * param2)474*a4cb5461SPaul Szczepanek test_ring_perf_esize_run_on_two_cores(
475*a4cb5461SPaul Szczepanek 		struct thread_params *param1, struct thread_params *param2)
476*a4cb5461SPaul Szczepanek {
477*a4cb5461SPaul Szczepanek 	struct lcore_pair cores;
478*a4cb5461SPaul Szczepanek 
479*a4cb5461SPaul Szczepanek 	if (get_two_hyperthreads(&cores) == 0) {
480*a4cb5461SPaul Szczepanek 		printf("\n### Testing using two hyperthreads ###\n");
481*a4cb5461SPaul Szczepanek 		if (run_on_core_pair(&cores, param1, param2) < 0)
482*a4cb5461SPaul Szczepanek 			return -1;
483*a4cb5461SPaul Szczepanek 	}
484*a4cb5461SPaul Szczepanek 	if (get_two_cores(&cores) == 0) {
485*a4cb5461SPaul Szczepanek 		printf("\n### Testing using two physical cores ###\n");
486*a4cb5461SPaul Szczepanek 		if (run_on_core_pair(&cores, param1, param2) < 0)
487*a4cb5461SPaul Szczepanek 			return -1;
488*a4cb5461SPaul Szczepanek 	}
489*a4cb5461SPaul Szczepanek 	if (get_two_sockets(&cores) == 0) {
490*a4cb5461SPaul Szczepanek 		printf("\n### Testing using two NUMA nodes ###\n");
491*a4cb5461SPaul Szczepanek 		if (run_on_core_pair(&cores, param1, param2) < 0)
492*a4cb5461SPaul Szczepanek 			return -1;
493*a4cb5461SPaul Szczepanek 	}
494*a4cb5461SPaul Szczepanek 	return 0;
495*a4cb5461SPaul Szczepanek }
496*a4cb5461SPaul Szczepanek 
4971fa5d009SHonnappa Nagarahalli /* Run all tests for a given element size */
4981fa5d009SHonnappa Nagarahalli static __rte_always_inline int
test_ring_perf_esize(const int esize)4991fa5d009SHonnappa Nagarahalli test_ring_perf_esize(const int esize)
500a9de470cSBruce Richardson {
5011fa5d009SHonnappa Nagarahalli 	struct rte_ring *r = NULL;
502*a4cb5461SPaul Szczepanek 	double results_enq[RTE_DIM(bulk_sizes)];
503*a4cb5461SPaul Szczepanek 	double results_deq[RTE_DIM(bulk_sizes)];
504*a4cb5461SPaul Szczepanek 	struct ring_params ring_params = {
505*a4cb5461SPaul Szczepanek 			.elem_size = esize, .ring_flags = TEST_RING_ELEM_BULK };
506*a4cb5461SPaul Szczepanek 	struct thread_params param1 = {
507*a4cb5461SPaul Szczepanek 			.ring_params = &ring_params, .results = results_enq };
508*a4cb5461SPaul Szczepanek 	struct thread_params param2 = {
509*a4cb5461SPaul Szczepanek 			.ring_params = &ring_params, .results = results_deq };
510a9de470cSBruce Richardson 
5111fa5d009SHonnappa Nagarahalli 	/*
5121fa5d009SHonnappa Nagarahalli 	 * Performance test for legacy/_elem APIs
5131fa5d009SHonnappa Nagarahalli 	 * SP-SC/MP-MC, single
5141fa5d009SHonnappa Nagarahalli 	 */
5151fa5d009SHonnappa Nagarahalli 	r = test_ring_create(RING_NAME, esize, RING_SIZE, rte_socket_id(), 0);
5161fa5d009SHonnappa Nagarahalli 	if (r == NULL)
5171fa5d009SHonnappa Nagarahalli 		goto test_fail;
5181fa5d009SHonnappa Nagarahalli 
5191fa5d009SHonnappa Nagarahalli 	printf("\n### Testing single element enq/deq ###\n");
5201fa5d009SHonnappa Nagarahalli 	if (test_single_enqueue_dequeue(r, esize,
5211fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE) < 0)
5221fa5d009SHonnappa Nagarahalli 		goto test_fail;
5231fa5d009SHonnappa Nagarahalli 	if (test_single_enqueue_dequeue(r, esize,
5241fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE) < 0)
5251fa5d009SHonnappa Nagarahalli 		goto test_fail;
5261fa5d009SHonnappa Nagarahalli 
5271fa5d009SHonnappa Nagarahalli 	printf("\n### Testing burst enq/deq ###\n");
5281fa5d009SHonnappa Nagarahalli 	if (test_burst_bulk_enqueue_dequeue(r, esize,
5291fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST) < 0)
5301fa5d009SHonnappa Nagarahalli 		goto test_fail;
5311fa5d009SHonnappa Nagarahalli 	if (test_burst_bulk_enqueue_dequeue(r, esize,
5321fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST) < 0)
5331fa5d009SHonnappa Nagarahalli 		goto test_fail;
5341fa5d009SHonnappa Nagarahalli 
5351fa5d009SHonnappa Nagarahalli 	printf("\n### Testing bulk enq/deq ###\n");
5361fa5d009SHonnappa Nagarahalli 	if (test_burst_bulk_enqueue_dequeue(r, esize,
5371fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK) < 0)
5381fa5d009SHonnappa Nagarahalli 		goto test_fail;
5391fa5d009SHonnappa Nagarahalli 	if (test_burst_bulk_enqueue_dequeue(r, esize,
5401fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK) < 0)
5411fa5d009SHonnappa Nagarahalli 		goto test_fail;
5421fa5d009SHonnappa Nagarahalli 
5431fa5d009SHonnappa Nagarahalli 	printf("\n### Testing empty bulk deq ###\n");
5441fa5d009SHonnappa Nagarahalli 	test_empty_dequeue(r, esize,
5451fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK);
5461fa5d009SHonnappa Nagarahalli 	test_empty_dequeue(r, esize,
5471fa5d009SHonnappa Nagarahalli 			TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
5481fa5d009SHonnappa Nagarahalli 
549*a4cb5461SPaul Szczepanek 	ring_params.r = r;
550a9de470cSBruce Richardson 
551*a4cb5461SPaul Szczepanek 	ring_params.ring_flags = TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK;
552*a4cb5461SPaul Szczepanek 	test_ring_perf_esize_run_on_two_cores(&param1, &param2);
553*a4cb5461SPaul Szczepanek 
554*a4cb5461SPaul Szczepanek 	ring_params.ring_flags = TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK;
555*a4cb5461SPaul Szczepanek 	test_ring_perf_esize_run_on_two_cores(&param1, &param2);
5561fa5d009SHonnappa Nagarahalli 
557cb056611SStephen Hemminger 	printf("\n### Testing using all worker nodes ###\n");
5581fa5d009SHonnappa Nagarahalli 	if (run_on_all_cores(r, esize) < 0)
5591fa5d009SHonnappa Nagarahalli 		goto test_fail;
5601fa5d009SHonnappa Nagarahalli 
5611fa5d009SHonnappa Nagarahalli 	rte_ring_free(r);
5621fa5d009SHonnappa Nagarahalli 
5631fa5d009SHonnappa Nagarahalli 	return 0;
5641fa5d009SHonnappa Nagarahalli 
5651fa5d009SHonnappa Nagarahalli test_fail:
5661fa5d009SHonnappa Nagarahalli 	rte_ring_free(r);
5671fa5d009SHonnappa Nagarahalli 
5681fa5d009SHonnappa Nagarahalli 	return -1;
569a9de470cSBruce Richardson }
570a9de470cSBruce Richardson 
571*a4cb5461SPaul Szczepanek 
572*a4cb5461SPaul Szczepanek static __rte_always_inline int
test_ring_perf_compression(void)573*a4cb5461SPaul Szczepanek test_ring_perf_compression(void)
574*a4cb5461SPaul Szczepanek {
575*a4cb5461SPaul Szczepanek 	double results1[RTE_DIM(bulk_sizes)];
576*a4cb5461SPaul Szczepanek 	double results2[RTE_DIM(bulk_sizes)];
577*a4cb5461SPaul Szczepanek 	double results1_comp[2][RTE_DIM(bulk_sizes)];
578*a4cb5461SPaul Szczepanek 	double results2_comp[2][RTE_DIM(bulk_sizes)];
579*a4cb5461SPaul Szczepanek 
580*a4cb5461SPaul Szczepanek 	struct lcore_pair cores;
581*a4cb5461SPaul Szczepanek 	int ret = -1;
582*a4cb5461SPaul Szczepanek 	unsigned int i, j;
583*a4cb5461SPaul Szczepanek 	struct ring_params ring_params = { .elem_size = sizeof(void *) };
584*a4cb5461SPaul Szczepanek 	struct thread_params param1 = {
585*a4cb5461SPaul Szczepanek 			.ring_params = &ring_params, .results = results1 };
586*a4cb5461SPaul Szczepanek 	struct thread_params param2 = {
587*a4cb5461SPaul Szczepanek 			.ring_params = &ring_params, .results = results2 };
588*a4cb5461SPaul Szczepanek 
589*a4cb5461SPaul Szczepanek 	printf("\n### Testing compression gain ###");
590*a4cb5461SPaul Szczepanek 
591*a4cb5461SPaul Szczepanek 	ring_params.r = rte_ring_create_elem(
592*a4cb5461SPaul Szczepanek 			RING_NAME, sizeof(void *),
593*a4cb5461SPaul Szczepanek 			RING_SIZE, rte_socket_id(),
594*a4cb5461SPaul Szczepanek 			RING_F_SP_ENQ | RING_F_SC_DEQ);
595*a4cb5461SPaul Szczepanek 
596*a4cb5461SPaul Szczepanek 	if (ring_params.r == NULL)
597*a4cb5461SPaul Szczepanek 		return -1;
598*a4cb5461SPaul Szczepanek 
599*a4cb5461SPaul Szczepanek 	if (get_two_cores(&cores) == 0) {
600*a4cb5461SPaul Szczepanek 		printf("\n### Testing zero copy ###\n");
601*a4cb5461SPaul Szczepanek 		ring_params.ring_flags = TEST_RING_ELEM_BURST_ZC;
602*a4cb5461SPaul Szczepanek 		ret = run_on_core_pair(&cores, &param1, &param2);
603*a4cb5461SPaul Szczepanek 	}
604*a4cb5461SPaul Szczepanek 
605*a4cb5461SPaul Szczepanek 	rte_ring_free(ring_params.r);
606*a4cb5461SPaul Szczepanek 
607*a4cb5461SPaul Szczepanek 	if (ret != 0)
608*a4cb5461SPaul Szczepanek 		return ret;
609*a4cb5461SPaul Szczepanek 
610*a4cb5461SPaul Szczepanek 	/* rings allow only multiples of 4 as sizes,
611*a4cb5461SPaul Szczepanek 	 * we allocate size 4 despite only using 2 bytes
612*a4cb5461SPaul Szczepanek 	 * and use half of RING_SIZE as the number of elements
613*a4cb5461SPaul Szczepanek 	 */
614*a4cb5461SPaul Szczepanek 	ring_params.r = rte_ring_create_elem(
615*a4cb5461SPaul Szczepanek 			RING_NAME, sizeof(uint32_t),
616*a4cb5461SPaul Szczepanek 			RING_SIZE / 2, rte_socket_id(),
617*a4cb5461SPaul Szczepanek 			RING_F_SP_ENQ | RING_F_SC_DEQ);
618*a4cb5461SPaul Szczepanek 
619*a4cb5461SPaul Szczepanek 	if (ring_params.r == NULL)
620*a4cb5461SPaul Szczepanek 		return -1;
621*a4cb5461SPaul Szczepanek 
622*a4cb5461SPaul Szczepanek 	param1.results = results1_comp[0];
623*a4cb5461SPaul Szczepanek 	param2.results = results2_comp[0];
624*a4cb5461SPaul Szczepanek 
625*a4cb5461SPaul Szczepanek 	if (get_two_cores(&cores) == 0) {
626*a4cb5461SPaul Szczepanek 		printf("\n### Testing zero copy with compression (16b) ###\n");
627*a4cb5461SPaul Szczepanek 		ring_params.ring_flags =
628*a4cb5461SPaul Szczepanek 				TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_16;
629*a4cb5461SPaul Szczepanek 		ret = run_on_core_pair(&cores, &param1, &param2);
630*a4cb5461SPaul Szczepanek 	}
631*a4cb5461SPaul Szczepanek 
632*a4cb5461SPaul Szczepanek 	rte_ring_free(ring_params.r);
633*a4cb5461SPaul Szczepanek 
634*a4cb5461SPaul Szczepanek 	if (ret != 0)
635*a4cb5461SPaul Szczepanek 		return ret;
636*a4cb5461SPaul Szczepanek 
637*a4cb5461SPaul Szczepanek 	ring_params.r = rte_ring_create_elem(
638*a4cb5461SPaul Szczepanek 			RING_NAME, sizeof(uint32_t),
639*a4cb5461SPaul Szczepanek 			RING_SIZE, rte_socket_id(),
640*a4cb5461SPaul Szczepanek 			RING_F_SP_ENQ | RING_F_SC_DEQ);
641*a4cb5461SPaul Szczepanek 
642*a4cb5461SPaul Szczepanek 	if (ring_params.r == NULL)
643*a4cb5461SPaul Szczepanek 		return -1;
644*a4cb5461SPaul Szczepanek 
645*a4cb5461SPaul Szczepanek 	param1.results = results1_comp[1];
646*a4cb5461SPaul Szczepanek 	param2.results = results2_comp[1];
647*a4cb5461SPaul Szczepanek 
648*a4cb5461SPaul Szczepanek 	if (get_two_cores(&cores) == 0) {
649*a4cb5461SPaul Szczepanek 		printf("\n### Testing zero copy with compression (32b) ###\n");
650*a4cb5461SPaul Szczepanek 		ring_params.ring_flags =
651*a4cb5461SPaul Szczepanek 				TEST_RING_ELEM_BURST_ZC_COMPRESS_PTR_32;
652*a4cb5461SPaul Szczepanek 		ret = run_on_core_pair(&cores, &param1, &param2);
653*a4cb5461SPaul Szczepanek 	}
654*a4cb5461SPaul Szczepanek 
655*a4cb5461SPaul Szczepanek 	rte_ring_free(ring_params.r);
656*a4cb5461SPaul Szczepanek 
657*a4cb5461SPaul Szczepanek 	for (j = 0; j < 2; j++) {
658*a4cb5461SPaul Szczepanek 		printf("\n### Potential gain from compression (%d-bit offsets) "
659*a4cb5461SPaul Szczepanek 		"###\n", (j + 1) * 16);
660*a4cb5461SPaul Szczepanek 		for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
661*a4cb5461SPaul Szczepanek 			const double result = results1[i] + results2[i];
662*a4cb5461SPaul Szczepanek 			const double result_comp = results1_comp[j][i] +
663*a4cb5461SPaul Szczepanek 				results2_comp[j][i];
664*a4cb5461SPaul Szczepanek 			const double gain = 100 - (result_comp / result) * 100;
665*a4cb5461SPaul Szczepanek 
666*a4cb5461SPaul Szczepanek 			printf("Gain of %5.1F%% for burst of %-3u elems\n",
667*a4cb5461SPaul Szczepanek 					gain, bulk_sizes[i]);
668*a4cb5461SPaul Szczepanek 		}
669*a4cb5461SPaul Szczepanek 	}
670*a4cb5461SPaul Szczepanek 
671*a4cb5461SPaul Szczepanek 	return ret;
672*a4cb5461SPaul Szczepanek }
673*a4cb5461SPaul Szczepanek 
674a9de470cSBruce Richardson static int
test_ring_perf(void)675a9de470cSBruce Richardson test_ring_perf(void)
676a9de470cSBruce Richardson {
6771fa5d009SHonnappa Nagarahalli 	/* Run all the tests for different element sizes */
6781fa5d009SHonnappa Nagarahalli 	if (test_ring_perf_esize(-1) == -1)
679a9de470cSBruce Richardson 		return -1;
680a9de470cSBruce Richardson 
6811fa5d009SHonnappa Nagarahalli 	if (test_ring_perf_esize(16) == -1)
6821fa5d009SHonnappa Nagarahalli 		return -1;
683a9de470cSBruce Richardson 
684*a4cb5461SPaul Szczepanek 	/* Test for performance gain of compression */
685*a4cb5461SPaul Szczepanek 	if (test_ring_perf_compression() == -1)
686*a4cb5461SPaul Szczepanek 		return -1;
687*a4cb5461SPaul Szczepanek 
688a9de470cSBruce Richardson 	return 0;
689a9de470cSBruce Richardson }
690a9de470cSBruce Richardson 
691e0a8442cSBruce Richardson REGISTER_PERF_TEST(ring_perf_autotest, test_ring_perf);
692