From 234fe894d80a6ebc7e457bc86f2eea80d5ef01ea Mon Sep 17 00:00:00 2001 From: Ryujiro Shibuya Date: Wed, 25 Dec 2019 07:40:54 +0000 Subject: session svm: tracking segment memory usage 1. segment manager would attempt to balance the usages across the segments, when it allocate fifos 2. the memory presure level is determined per fifo-segment 3. updated unit test 4. updated cli output for segments Type: feature Signed-off-by: Ryujiro Shibuya Change-Id: I2923f3e0a43dd919196a0cb2cd55e098fde6cf66 --- src/vnet/session/application.c | 7 ++- src/vnet/session/application_interface.h | 2 + src/vnet/session/segment_manager.c | 89 ++++++++++++++++++++++++++------ src/vnet/session/segment_manager.h | 11 +++- 4 files changed, 90 insertions(+), 19 deletions(-) (limited to 'src/vnet') diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c index 646d6b6de2c..0dcb3e6ad94 100644 --- a/src/vnet/session/application.c +++ b/src/vnet/session/application.c @@ -550,6 +550,10 @@ application_alloc_and_init (app_init_args_t * a) props->use_mq_eventfd = 1; if (options[APP_OPTIONS_TLS_ENGINE]) app->tls_engine = options[APP_OPTIONS_TLS_ENGINE]; + if (options[APP_OPTIONS_HIGH_WATERMARK]) + props->high_watermark = options[APP_OPTIONS_HIGH_WATERMARK]; + if (options[APP_OPTIONS_LOW_WATERMARK]) + props->low_watermark = options[APP_OPTIONS_LOW_WATERMARK]; props->segment_type = seg_type; /* Add app to lookup by api_client_index table */ @@ -698,8 +702,7 @@ application_alloc_worker_and_init (application_t * app, app_worker_t ** wrk) sm = segment_manager_alloc (); sm->app_wrk_index = app_wrk->wrk_index; - if ((rv = segment_manager_init (sm, app->sm_properties.segment_size, - app->sm_properties.prealloc_fifos))) + if ((rv = segment_manager_init (sm))) { app_worker_free (app_wrk); return rv; diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h index 552fec1b6ef..d03994fc1f9 100644 --- a/src/vnet/session/application_interface.h +++ b/src/vnet/session/application_interface.h @@ -201,6 +201,8 @@ typedef enum APP_OPTIONS_PROXY_TRANSPORT, APP_OPTIONS_ACCEPT_COOKIE, APP_OPTIONS_TLS_ENGINE, + APP_OPTIONS_HIGH_WATERMARK, + APP_OPTIONS_LOW_WATERMARK, APP_OPTIONS_N_OPTIONS } app_attach_options_index_t; diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 0a54b96a125..25fbd6f2c04 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -29,6 +29,8 @@ typedef struct segment_manager_main_ u32 default_fifo_size; /**< default rx/tx fifo size */ u32 default_segment_size; /**< default fifo segment size */ u32 default_app_mq_size; /**< default app msg q size */ + u8 default_high_watermark; /**< default high watermark % */ + u8 default_low_watermark; /**< default low watermark % */ } segment_manager_main_t; static segment_manager_main_t sm_main; @@ -54,6 +56,8 @@ segment_manager_props_init (segment_manager_props_t * props) props->rx_fifo_size = sm_main.default_fifo_size; props->tx_fifo_size = sm_main.default_fifo_size; props->evt_q_size = sm_main.default_app_mq_size; + props->high_watermark = sm_main.default_high_watermark; + props->low_watermark = sm_main.default_low_watermark; props->n_slices = vlib_num_workers () + 1; return props; } @@ -160,6 +164,13 @@ segment_manager_add_segment (segment_manager_t * sm, uword segment_size) */ fs_index = fs - sm->segments; + /* + * Set watermarks in segment + */ + fs->h->high_watermark = sm->high_watermark; + fs->h->low_watermark = sm->low_watermark; + fs->h->flags &= ~FIFO_SEGMENT_F_MEM_LIMIT; + done: if (vlib_num_workers ()) @@ -307,11 +318,12 @@ segment_manager_alloc (void) * Returns error if ssvm segment(s) allocation fails. */ int -segment_manager_init (segment_manager_t * sm, uword first_seg_size, - u32 prealloc_fifo_pairs) +segment_manager_init (segment_manager_t * sm) { u32 rx_fifo_size, tx_fifo_size, pair_size; u32 rx_rounded_data_size, tx_rounded_data_size; + uword first_seg_size; + u32 prealloc_fifo_pairs; u64 approx_total_size, max_seg_size = ((u64) 1 << 32) - (128 << 10); segment_manager_props_t *props; fifo_segment_t *segment; @@ -319,7 +331,13 @@ segment_manager_init (segment_manager_t * sm, uword first_seg_size, int seg_index, i; props = segment_manager_properties_get (sm); - first_seg_size = clib_max (first_seg_size, sm_main.default_segment_size); + first_seg_size = clib_max (props->segment_size, + sm_main.default_segment_size); + prealloc_fifo_pairs = props->prealloc_fifos; + + segment_manager_set_watermarks (sm, + props->high_watermark, + props->low_watermark); if (prealloc_fifo_pairs) { @@ -434,6 +452,27 @@ segment_manager_get_if_valid (u32 index) return pool_elt_at_index (sm_main.segment_managers, index); } +static fifo_segment_t * +find_max_free_segment (segment_manager_t * sm, u32 thread_index) +{ + fifo_segment_t *cur, *fs = 0; + uword free_bytes, max_free_bytes = 0; + + clib_rwlock_reader_lock (&sm->segments_rwlock); + /* *INDENT-OFF* */ + pool_foreach (cur, sm->segments, ({ + if ((free_bytes = fifo_segment_free_bytes (cur)) > max_free_bytes) + { + max_free_bytes = free_bytes; + fs = cur; + } + })); + /* *INDENT-ON* */ + clib_rwlock_reader_unlock (&sm->segments_rwlock); + + return fs; +} + u32 segment_manager_index (segment_manager_t * sm) { @@ -569,19 +608,25 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, /* * Find the first free segment to allocate the fifos in */ + fs = find_max_free_segment (sm, thread_index); - /* *INDENT-OFF* */ - segment_manager_foreach_segment_w_lock (fs, sm, ({ - alloc_fail = segment_manager_try_alloc_fifos (fs, - thread_index, - props->rx_fifo_size, - props->tx_fifo_size, - rx_fifo, tx_fifo); - /* Exit with lock held, drop it after notifying app */ - if (!alloc_fail) - goto alloc_success; - })); - /* *INDENT-ON* */ + if (fs) + { + clib_rwlock_reader_lock (&sm->segments_rwlock); + alloc_fail = segment_manager_try_alloc_fifos (fs, thread_index, + props->rx_fifo_size, + props->tx_fifo_size, + rx_fifo, tx_fifo); + /* On success, keep lock until fifos are initialized */ + if (!alloc_fail) + goto alloc_success; + + segment_manager_segment_reader_unlock (sm); + } + else + { + alloc_fail = 1; + } alloc_check: @@ -787,6 +832,8 @@ segment_manager_main_init (segment_manager_main_init_args_t * a) sm->default_fifo_size = 1 << 12; sm->default_segment_size = 1 << 20; sm->default_app_mq_size = 128; + sm->default_high_watermark = 80; + sm->default_low_watermark = 50; } static clib_error_t * @@ -910,6 +957,18 @@ segment_manager_format_sessions (segment_manager_t * sm, int verbose) clib_rwlock_reader_unlock (&sm->segments_rwlock); } +void +segment_manager_set_watermarks (segment_manager_t * sm, + u8 high_watermark, u8 low_watermark) +{ + ASSERT (high_watermark >= 0 && high_watermark <= 100 && + low_watermark >= 0 && low_watermark <= 100 && + low_watermark <= high_watermark); + + sm->high_watermark = high_watermark; + sm->low_watermark = low_watermark; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h index 52f89eef171..cad95509b2e 100644 --- a/src/vnet/session/segment_manager.h +++ b/src/vnet/session/segment_manager.h @@ -34,6 +34,8 @@ typedef struct _segment_manager_props u8 n_slices; /**< number of fs slices/threads */ ssvm_segment_type_t segment_type; /**< seg type: if set to SSVM_N_TYPES, private segments are used */ + u8 high_watermark; /**< memory usage high watermark % */ + u8 low_watermark; /**< memory usage low watermark % */ } segment_manager_props_t; typedef struct _segment_manager @@ -58,6 +60,9 @@ typedef struct _segment_manager * App event queue allocated in first segment */ svm_msg_q_t *event_queue; + + u8 high_watermark; + u8 low_watermark; } segment_manager_t; typedef struct segment_manager_main_init_args_ @@ -69,8 +74,7 @@ typedef struct segment_manager_main_init_args_ #define SEGMENT_MANAGER_INVALID_APP_INDEX ((u32) ~0) segment_manager_t *segment_manager_alloc (void); -int segment_manager_init (segment_manager_t * sm, uword first_seg_size, - u32 prealloc_fifo_pairs); +int segment_manager_init (segment_manager_t * sm); /** * Cleanup segment manager @@ -118,6 +122,9 @@ int segment_manager_try_alloc_fifos (fifo_segment_t * fs, void segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo); +void segment_manager_set_watermarks (segment_manager_t * sm, + u8 high_watermark, u8 low_watermark); + u8 segment_manager_has_fifos (segment_manager_t * sm); svm_msg_q_t *segment_manager_alloc_queue (fifo_segment_t * fs, -- cgit 1.2.3-korg