From 28aa539f7da7b172d0f35ea9a63f3986939477f7 Mon Sep 17 00:00:00 2001 From: Sirshak Das Date: Tue, 5 Feb 2019 01:33:33 -0600 Subject: svm_fifo rework to avoid contention on cursize Problems Addressed: - Contention of cursize by producer and consumer. - Reduce the no of modulo operations. Changes: - Synchronization between producer and consumer changed from cursize to head and tail indexes Implications: reduces the usable size of fifo by 1. - Using weaker memory ordering C++11 atomics to access head and tail based on producer and consumer role. - Head and tail indexes are unsigned 32 bit integers. Additions and subtraction on them are implicit 32 bit Modulo operation. - Adding weaker memory ordering variants of max_enq, max_deq, is_empty and is_full Using them appropriately in all places. Perfomance improvement (iperf3 via Hoststack): iperf3 Server: Marvell ThunderX2(AArch64) - iperf3 Client: Skylake(x86) ~6%(256 rxd/txd) - ~11%(2048 rxd/txd) Change-Id: I1d484e000e437430fdd5a819657d1c6b62443018 Signed-off-by: Sirshak Das Reviewed-by: Honnappa Nagarahalli --- src/vnet/session/application_interface.h | 4 ++-- src/vnet/session/application_worker.c | 19 +++++-------------- src/vnet/session/session.c | 6 +++--- src/vnet/session/session.h | 4 ++-- src/vnet/session/session_node.c | 10 ++++++---- 5 files changed, 18 insertions(+), 25 deletions(-) (limited to 'src/vnet/session') diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h index 8323e72e768..b49744c0b29 100644 --- a/src/vnet/session/application_interface.h +++ b/src/vnet/session/application_interface.h @@ -459,7 +459,7 @@ app_send_dgram_raw (svm_fifo_t * f, app_session_transport_t * at, session_dgram_hdr_t hdr; int rv; - max_enqueue = svm_fifo_max_enqueue (f); + max_enqueue = svm_fifo_max_enqueue_prod (f); if (max_enqueue <= sizeof (session_dgram_hdr_t)) return 0; @@ -533,7 +533,7 @@ app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len, u32 max_deq; int rv; - max_deq = svm_fifo_max_dequeue (f); + max_deq = svm_fifo_max_dequeue_cons (f); if (max_deq < sizeof (session_dgram_hdr_t)) { if (clear_evt) diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c index a8edad3edbb..dd1088e2cbb 100644 --- a/src/vnet/session/application_worker.c +++ b/src/vnet/session/application_worker.c @@ -369,21 +369,12 @@ app_worker_own_session (app_worker_t * app_wrk, session_t * s) if (app_worker_alloc_session_fifos (sm, s)) return -1; - if (!svm_fifo_is_empty (rxf)) - { - clib_memcpy_fast (s->rx_fifo->data, rxf->data, rxf->nitems); - s->rx_fifo->head = rxf->head; - s->rx_fifo->tail = rxf->tail; - s->rx_fifo->cursize = rxf->cursize; - } + if (!svm_fifo_is_empty_cons (rxf)) + svm_fifo_clone (s->rx_fifo, rxf); + + if (!svm_fifo_is_empty_cons (txf)) + svm_fifo_clone (s->tx_fifo, txf); - if (!svm_fifo_is_empty (txf)) - { - clib_memcpy_fast (s->tx_fifo->data, txf->data, txf->nitems); - s->tx_fifo->head = txf->head; - s->tx_fifo->tail = txf->tail; - s->tx_fifo->cursize = txf->cursize; - } segment_manager_dealloc_fifos (rxf, txf); diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 90248b64401..58ec1c01369 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -411,7 +411,7 @@ session_enqueue_dgram_connection (session_t * s, { int enqueued = 0, rv, in_order_off; - ASSERT (svm_fifo_max_enqueue (s->rx_fifo) + ASSERT (svm_fifo_max_enqueue_prod (s->rx_fifo) >= b->current_length + sizeof (*hdr)); svm_fifo_enqueue_nowait (s->rx_fifo, sizeof (session_dgram_hdr_t), @@ -508,7 +508,7 @@ session_enqueue_notify_inline (session_t * s) /* *INDENT-OFF* */ SESSION_EVT_DBG(SESSION_EVT_ENQ, s, ({ ed->data[0] = SESSION_IO_EVT_RX; - ed->data[1] = svm_fifo_max_dequeue (s->rx_fifo); + ed->data[1] = svm_fifo_max_dequeue_prod (s->rx_fifo); })); /* *INDENT-ON* */ @@ -1112,7 +1112,7 @@ session_transport_close (session_t * s) * point, either after sending everything or after a timeout, call delete * notify. This will finally lead to the complete cleanup of the session. */ - if (svm_fifo_max_dequeue (s->tx_fifo)) + if (svm_fifo_max_dequeue_cons (s->tx_fifo)) s->session_state = SESSION_STATE_CLOSED_WAITING; else s->session_state = SESSION_STATE_CLOSED; diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index ed42e5476e9..997d15395ef 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -378,14 +378,14 @@ always_inline u32 transport_max_rx_enqueue (transport_connection_t * tc) { session_t *s = session_get (tc->s_index, tc->thread_index); - return svm_fifo_max_enqueue (s->rx_fifo); + return svm_fifo_max_enqueue_prod (s->rx_fifo); } always_inline u32 transport_max_tx_dequeue (transport_connection_t * tc) { session_t *s = session_get (tc->s_index, tc->thread_index); - return svm_fifo_max_dequeue (s->tx_fifo); + return svm_fifo_max_dequeue_cons (s->tx_fifo); } always_inline u32 diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index 2eac5152e16..c894c437cde 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -82,7 +82,8 @@ session_mq_accepted_reply_handler (void *data) { old_state = s->session_state; s->session_state = SESSION_STATE_READY; - if (!svm_fifo_is_empty (s->rx_fifo)) + + if (!svm_fifo_is_empty_prod (s->rx_fifo)) app_worker_lock_and_send_event (app_wrk, s, SESSION_IO_EVT_RX); /* Closed while waiting for app to reply. Resend disconnect */ @@ -557,7 +558,7 @@ session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx, u32 max_segs, u8 peek_data) { u32 n_bytes_per_buf, n_bytes_per_seg; - ctx->max_dequeue = svm_fifo_max_dequeue (ctx->s->tx_fifo); + ctx->max_dequeue = svm_fifo_max_dequeue_cons (ctx->s->tx_fifo); if (peek_data) { /* Offset in rx fifo from where to peek data */ @@ -788,7 +789,7 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node, svm_fifo_overwrite_head (ctx->s->tx_fifo, (u8 *) & ctx->hdr, sizeof (session_dgram_pre_hdr_t)); /* More data needs to be read */ - else if (svm_fifo_max_dequeue (ctx->s->tx_fifo) > 0) + else if (svm_fifo_max_dequeue_cons (ctx->s->tx_fifo) > 0) if (svm_fifo_set_event (ctx->s->tx_fifo)) vec_add1 (wrk->pending_event_vector, *e); } @@ -956,7 +957,8 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, * and the tx queue is still not empty, try to wait for some * dispatch cycles */ if (!e->postponed - || (e->postponed < 200 && svm_fifo_max_dequeue (s->tx_fifo))) + || (e->postponed < 200 + && svm_fifo_max_dequeue_cons (s->tx_fifo))) { e->postponed += 1; vec_add1 (wrk->pending_disconnects, *e); -- cgit 1.2.3-korg