From cf2562cddf7c32c540ef55d1f5a28094b972fb2f Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Fri, 29 Aug 2025 13:34:10 +0000 Subject: [PATCH] OPTIM: stats-file: don't unnecessarily die hard on shm_stats_file_reuse_object() shm_stats_file_reuse_object() has a non negligible cost, especially if the shm file contains a lot of objects because the functions scans the whole shm file to find available slots. During startup, if no existing objects could be mapped in the shm file shm_stats_file_add_object() for each object (server, fe, be or listener) with a GUID set. On large config it means shm_stats_file_add_object() could be called a lot of times in a row. With current implementation, each shm_stats_file_add_object() call leverages shm_stats_file_reuse_object(), so the more objects are defined in the config, the slower the startup will be. To try to optimize startup time a bit with large configs, we don't sytematically call shm_stats_file_reuse_object(), especially when we know that the previous attempt to reuse objects failed. In this case we add a small tempo between failed attempts to reuse objects because we assume the new attempt will probably fail anyway. (For slots to become available, either an old process has to clean its entries, or they have to time out which implies that the clock needs to be updated) --- src/stats-file.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/stats-file.c b/src/stats-file.c index 2a3cef6bb..e9050e89a 100644 --- a/src/stats-file.c +++ b/src/stats-file.c @@ -616,11 +616,24 @@ struct shm_stats_file_object *shm_stats_file_add_object(char **errmsg) struct shm_stats_file_object *new_obj; uint64_t expected_users; int objects, objects_slots; + static uint last_failed_attempt = TICK_ETERNITY; + + /* if previous object reuse failed, don't try a new opportunistic + * reuse immediately because chances are high the new reuse attempt + * will also fail, and repeated failed reuse attempts could be costly + * with large number of objects + */ + if (last_failed_attempt != TICK_ETERNITY && + !tick_is_expired(last_failed_attempt + MS_TO_TICKS(50), now_ms)) + goto add; new_obj = shm_stats_file_reuse_object(); if (new_obj) { + last_failed_attempt = TICK_ETERNITY; return new_obj; } + else + last_failed_attempt = now_ms; add: objects = HA_ATOMIC_LOAD(&shm_stats_file_hdr->objects);