MEDIUM: stick-table: make stktable_set_entry() look up under a read lock

On a 24-core machine having some "stick-store response" rules, a lot of
time is spent in the write lock in stktable_set_entry(). Let's apply the
same mechanism as for the stktable_get_entry() consisting in looking up
the value under the read lock and upgrading it to a write lock only to
perform modifications. Here we even have the luxury of upgrading the
lock since there are no alloc/free in the path. All this increases the
performance by 40% (from 363k to 510k rps).
This commit is contained in:
Willy Tarreau 2022-10-12 09:13:14 +00:00
parent 996f1a5124
commit e62885237c

View File

@ -552,35 +552,40 @@ struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *
} }
/* Lookup for an entry with the same key and store the submitted /* Lookup for an entry with the same key and store the submitted
* stksess if not found. * stksess if not found. This function locks the table either shared or
*/ * exclusively, and the refcount of the entry is increased.
struct stksess *__stktable_set_entry(struct stktable *table, struct stksess *nts)
{
struct stksess *ts;
ts = __stktable_lookup(table, nts);
if (ts == NULL) {
ts = nts;
__stktable_store(table, ts);
}
return ts;
}
/* Lookup for an entry with the same key and store the submitted
* stksess if not found.
* This function locks the table, and the refcount of the entry is increased.
*/ */
struct stksess *stktable_set_entry(struct stktable *table, struct stksess *nts) struct stksess *stktable_set_entry(struct stktable *table, struct stksess *nts)
{ {
struct stksess *ts; struct stksess *ts;
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &table->lock); HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &table->lock);
ts = __stktable_set_entry(table, nts); ts = __stktable_lookup(table, nts);
ts->ref_cnt++; if (ts) {
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &table->lock); HA_ATOMIC_INC(&ts->ref_cnt);
HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &table->lock);
return ts; return ts;
} }
ts = nts;
/* let's increment it before switching to exclusive */
HA_ATOMIC_INC(&ts->ref_cnt);
if (HA_RWLOCK_TRYRDTOSK(STK_TABLE_LOCK, &table->lock) != 0) {
/* upgrade to seek lock failed, let's drop and take */
HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &table->lock);
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &table->lock);
}
else
HA_RWLOCK_SKTOWR(STK_TABLE_LOCK, &table->lock);
/* now we're write-locked */
__stktable_store(table, ts);
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &table->lock);
return ts;
}
/* /*
* Trash expired sticky sessions from table <t>. The next expiration date is * Trash expired sticky sessions from table <t>. The next expiration date is
* returned. * returned.