MEDIUM: logs: atomically check and update the log sample index
authorWilly Tarreau <w@1wt.eu>
Wed, 20 Sep 2023 18:34:35 +0000 (20:34 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 20 Sep 2023 19:38:33 +0000 (21:38 +0200)
commitcec8b42cb391f48e578ed7860d749d6735f6ef8e
tree64d4112b1ba64a4b86c1a6c20e067b2fc33b9f4e
parente00470378bcd55321d649f21cd5d4df3318e2774
MEDIUM: logs: atomically check and update the log sample index

The log server lock is pretty visible in perf top when using log samples
because it's taken for each server in turn while trying to validate and
update the log server's index. Let's change this for a CAS, since we have
the index and the range at hand now. This allow us to remove the logsrv
lock.

The test on 4 servers now shows a 3.7 times improvement thanks to much
lower contention. Without log sampling a test producing 4.4M logs/s
delivers 4.4M logs/s at 21 CPUs used, everything spent in the kernel.
After enabling 4 samples (1:4, 2:4, 3:4 and 4:4), the throughput would
previously drop to 1.13M log/s with 37 CPUs used and 75% spent in
process_send_log(). Now with this change, 4.25M logs/s are emitted,
using 26 CPUs and 22% in process_send_log(). That's a 3.7x throughput
improvement for a 30% global CPU usage reduction, but in practice it
mostly shows that the performance drop caused by having samples is much
less noticeable (each of the 4 servers has its index updated for each
log).

Note that in order to even avoid incrementing an index for each log srv
that is consulted, it would be more convenient to have a single index
per frontend and apply the modulus on each log server in turn to see if
the range has to be updated. It would then only perform one write per
range switch. However the place where this is done doesn't have access
to a frontend, so some changes would need to be performed for this, and
it would require to update the current range independently in each
logsrv, which is not necessarily easier since we don't know yet if we
can commit it.
include/haproxy/log-t.h
src/log.c