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)
This commit is contained in:
Aurelien DARRAGON 2025-08-29 13:34:10 +00:00
parent 16abfb6e06
commit cf2562cddf

View File

@ -616,11 +616,24 @@ struct shm_stats_file_object *shm_stats_file_add_object(char **errmsg)
struct shm_stats_file_object *new_obj; struct shm_stats_file_object *new_obj;
uint64_t expected_users; uint64_t expected_users;
int objects, objects_slots; 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(); new_obj = shm_stats_file_reuse_object();
if (new_obj) { if (new_obj) {
last_failed_attempt = TICK_ETERNITY;
return new_obj; return new_obj;
} }
else
last_failed_attempt = now_ms;
add: add:
objects = HA_ATOMIC_LOAD(&shm_stats_file_hdr->objects); objects = HA_ATOMIC_LOAD(&shm_stats_file_hdr->objects);