OPTIM: stick-tables: check the stksess without taking the read lock

Thanks to the previous commit, we can now simply perform an atomic read
on stksess->seen and take the write lock to recreate the entry only if
at least one peer has seen it, otherwise leave it untouched. On a test
on 40 cores, the performance used to drop from 2.10 to 1.14M RPS when
one peer was connected, now it drops to 2.05, thus there's basically
no impact of connecting a peer vs ~45% previously, all spent in the
read lock. This can be particularly important when often updating the
same entries (user-agent, source address during an attack etc).
This commit is contained in:
Willy Tarreau 2024-04-02 19:04:12 +02:00
parent 4c1480f13b
commit 864ac31174

View File

@ -475,7 +475,7 @@ struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts)
* The node will be also inserted into the update tree if needed, at a position
* depending if the update is a local or coming from a remote node.
* If <decrefcnt> is set, the ts entry's ref_cnt will be decremented. The table's
* write lock may be taken.
* updt_lock may be taken for writes.
*/
void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local, int expire, int decrefcnt)
{
@ -491,7 +491,6 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
/* If sync is enabled */
if (t->sync_task) {
try_lock_again:
/* We'll need to reliably check that the entry is in the tree.
* It's only inserted/deleted using a write lock so a read lock
* is sufficient to verify this. We may then need to upgrade it
@ -500,25 +499,15 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
*/
if (use_wrlock)
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
else
HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &t->updt_lock);
if (local) {
/* Check if this entry is not in the tree or not
* scheduled for at least one peer.
*/
if (!ts->upd.node.leaf_p
|| (int)(t->commitupdate - ts->upd.key) >= 0
|| (int)(ts->upd.key - t->localupdate) >= 0) {
if (!ts->upd.node.leaf_p || _HA_ATOMIC_LOAD(&ts->seen)) {
/* Time to upgrade the read lock to write lock if needed */
if (!use_wrlock) {
if (HA_RWLOCK_TRYRDTOSK(STK_TABLE_LOCK, &t->updt_lock) != 0) {
/* failed, try again */
HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
use_wrlock = 1;
goto try_lock_again;
}
HA_RWLOCK_SKTOWR(STK_TABLE_LOCK, &t->updt_lock);
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
use_wrlock = 1;
}
@ -542,13 +531,7 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
if (!ts->upd.node.leaf_p) {
/* Time to upgrade the read lock to write lock if needed */
if (!use_wrlock) {
if (HA_RWLOCK_TRYRDTOSK(STK_TABLE_LOCK, &t->updt_lock) != 0) {
/* failed, try again */
HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
use_wrlock = 1;
goto try_lock_again;
}
HA_RWLOCK_SKTOWR(STK_TABLE_LOCK, &t->updt_lock);
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
use_wrlock = 1;
}
@ -567,8 +550,6 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
/* drop the lock now */
if (use_wrlock)
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
else
HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
}
if (decrefcnt)