Since 2.9-dev3 with commit
7bf829ace ("MAJOR: pools: move the shared
pool's free_list over multiple buckets"), the global pool supports
multiple heads to reduce inter-thread contention. However, when
grabbing a freelist head fails because another thread is already
picking from it, we just skip to the next one and try again.
Unfortunately, it still maintains a bit of contention between thread
pairs when for some reasons only a few threads are used. This may
happen for example when running on a 4- or 8- thread system and
the two most active ones end up on adjacent buckets.
A better and much simpler solution consists in visiting a random bucket
instead of the current one. Tests show that the CPU usage spent in
pool_refill_local_from_shared() reduces at low number of connections
(hence threads).
No backport is needed, as the issue is only in 2.9.
do {
/* look for an apparently non-busy entry */
while (unlikely(ret == POOL_BUSY)) {
- bucket = (bucket + 1) % CONFIG_HAP_POOL_BUCKETS;
+ bucket = statistical_prng() % CONFIG_HAP_POOL_BUCKETS;
ret = _HA_ATOMIC_LOAD(&pool->buckets[bucket].free_list);
}
if (ret == NULL)