MEDIUM: peers: Give up if we fail to take locks in hot path
In peer_send_msgs(), give up in order to retry later if we failed at getting the update read lock. Similarly, in __process_running_peer_sync(), give up and just reschedule the task if we failed to get the peer lock. There is an heavy contention on both those locks, so we could spend a lot of time trying to get them. This helps getting peers perform better under heavy load.
This commit is contained in:
parent
7a8d1a3122
commit
b3ad7b6371
16
src/peers.c
16
src/peers.c
@ -2639,7 +2639,10 @@ static inline int peer_send_msgs(struct appctx *appctx,
|
||||
if (!(peer->flags & PEER_F_TEACH_PROCESS)) {
|
||||
int must_send;
|
||||
|
||||
HA_RWLOCK_RDLOCK(STK_TABLE_UPDT_LOCK, &st->table->updt_lock);
|
||||
if (HA_RWLOCK_TRYRDLOCK(STK_TABLE_UPDT_LOCK, &st->table->updt_lock)) {
|
||||
applet_have_more_data(appctx);
|
||||
return -1;
|
||||
}
|
||||
must_send = (peer->learnstate == PEER_LR_ST_NOTASSIGNED) && (st->last_pushed != st->table->localupdate);
|
||||
HA_RWLOCK_RDUNLOCK(STK_TABLE_UPDT_LOCK, &st->table->updt_lock);
|
||||
|
||||
@ -3413,6 +3416,7 @@ static void __process_running_peer_sync(struct task *task, struct peers *peers,
|
||||
{
|
||||
struct peer *peer;
|
||||
struct shared_table *st;
|
||||
int must_resched = 0;
|
||||
|
||||
/* resync timeout set to TICK_ETERNITY means we just start
|
||||
* a new process and timer was not initialized.
|
||||
@ -3440,7 +3444,10 @@ static void __process_running_peer_sync(struct task *task, struct peers *peers,
|
||||
|
||||
/* For each session */
|
||||
for (peer = peers->remote; peer; peer = peer->next) {
|
||||
HA_SPIN_LOCK(PEER_LOCK, &peer->lock);
|
||||
if (HA_SPIN_TRYLOCK(PEER_LOCK, &peer->lock) != 0) {
|
||||
must_resched = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
sync_peer_learn_state(peers, peer);
|
||||
sync_peer_app_state(peers, peer);
|
||||
@ -3567,12 +3574,13 @@ static void __process_running_peer_sync(struct task *task, struct peers *peers,
|
||||
HA_ATOMIC_OR(&peers->flags, PEERS_F_RESYNC_REMOTE_FINISHED|PEERS_F_DBG_RESYNC_REMOTETIMEOUT);
|
||||
}
|
||||
|
||||
if ((peers->flags & PEERS_RESYNC_STATEMASK) != PEERS_RESYNC_FINISHED) {
|
||||
if (!must_resched && (peers->flags & PEERS_RESYNC_STATEMASK) != PEERS_RESYNC_FINISHED) {
|
||||
/* Resync not finished*/
|
||||
/* reschedule task to resync timeout if not expired, to ended resync if needed */
|
||||
if (!tick_is_expired(peers->resync_timeout, now_ms))
|
||||
task->expire = tick_first(task->expire, peers->resync_timeout);
|
||||
}
|
||||
} else if (must_resched)
|
||||
task_wakeup(task, TASK_WOKEN_OTHER);
|
||||
}
|
||||
|
||||
/* Process the sync task for a stopping process. It is called from process_peer_sync() only */
|
||||
|
Loading…
x
Reference in New Issue
Block a user