mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
MINOR: check: also consider the random other thread's active checks
When checking if it's worth transferring a sleeping thread to another random thread, let's also check if that random other thread has less checks than the current one, which is another reason for transferring the load there. This commit adds a function "check_thread_cmp_load()" to compare two threads' loads in order to simplify the decision taking. The minimum active check count before starting to consider rebalancing the load was now raised from 2 to 3, because tests show that at 15k concurrent checks, at 2, 50% are evaluated for rebalancing and 30% are rebalanced, while at 3, this is cut in half.
This commit is contained in:
parent
00de9e0804
commit
016e189ea3
38
src/check.c
38
src/check.c
@ -1106,6 +1106,39 @@ struct task *srv_chk_io_cb(struct task *t, void *ctx, unsigned int state)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns <0, 0, >0 if check thread 1 is respectively less loaded than,
|
||||
* equally as, or more loaded than thread 2. This is made to decide on
|
||||
* migrations so a margin is applied in either direction. For ease of
|
||||
* remembering the direction, consider this returns load1 - load2.
|
||||
*/
|
||||
static inline int check_thread_cmp_load(int thr1, int thr2)
|
||||
{
|
||||
uint t1_load = _HA_ATOMIC_LOAD(&ha_thread_ctx[thr1].rq_total);
|
||||
uint t1_act = _HA_ATOMIC_LOAD(&ha_thread_ctx[thr1].active_checks);
|
||||
uint t2_load = _HA_ATOMIC_LOAD(&ha_thread_ctx[thr2].rq_total);
|
||||
uint t2_act = _HA_ATOMIC_LOAD(&ha_thread_ctx[thr2].active_checks);
|
||||
|
||||
/* twice as more active checks is a significant difference */
|
||||
if (t1_act * 2 < t2_act)
|
||||
return -1;
|
||||
|
||||
if (t2_act * 2 < t1_act)
|
||||
return 1;
|
||||
|
||||
/* twice as more rqload with more checks is also a significant
|
||||
* difference.
|
||||
*/
|
||||
if (t1_act <= t2_act && t1_load * 2 < t2_load)
|
||||
return -1;
|
||||
|
||||
if (t2_act <= t1_act && t2_load * 2 < t1_load)
|
||||
return 1;
|
||||
|
||||
/* otherwise they're roughly equal */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* manages a server health-check that uses a connection. Returns
|
||||
* the time the task accepts to wait, or TIME_ETERNITY for infinity.
|
||||
*
|
||||
@ -1141,11 +1174,10 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
|
||||
/* check was migrated, active already counted */
|
||||
activity[tid].check_adopted++;
|
||||
}
|
||||
else if (my_load >= 2) {
|
||||
else if (my_load >= 3 && th_ctx->active_checks >= 3) {
|
||||
uint new_tid = statistical_prng_range(global.nbthread);
|
||||
uint new_load = HA_ATOMIC_LOAD(&ha_thread_ctx[new_tid].rq_total);
|
||||
|
||||
if (new_load <= my_load / 2) {
|
||||
if (check_thread_cmp_load(tid, new_tid) > 0) {
|
||||
/* Found one. Let's migrate the task over there. We have to
|
||||
* remove it from the WQ first and kill its expire time
|
||||
* otherwise the scheduler will reinsert it and trigger a
|
||||
|
Loading…
Reference in New Issue
Block a user