BUG/MEDIUM: stats: don't ask for more data as long as we're responding
authorWilly Tarreau <w@1wt.eu>
Tue, 24 Jul 2018 15:05:54 +0000 (17:05 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 24 Jul 2018 15:13:32 +0000 (17:13 +0200)
commit055ba4f505e5117f59d3b843afc4c737dd2e21d5
treed5d0dff928b97cbe14001a4cb98ab723652deb78
parent171d5f203a7091f271fee2c513a1e00d5639ee38
BUG/MEDIUM: stats: don't ask for more data as long as we're responding

The stats applet is still a bit hackish. It uses the HTTP txn to parse
the POST contents. Due to this it pretends not having parsed the request
from the buffer so that the HTTP parser continues to work fine on these
data. This comes with a side effect : the request lies pending in the
channel's buffer, and because of this, stream_int_update_applet() always
wakes the applet up. It's very visible when retrieving a large stats page
over a slow link as haproxy eats 100% of the CPU waiting for the data to
leave.

While the proper long term solution definitely is to consume these data
and parse the body from the applet, changing this is not suitable for a
fix.

What this patch does instead is to disable request polling as long as there
are pending data in the response buffer. Given that for almost all cases,
the applet remains busy sending data, this is at least enough to ensure
that we don't wake up for the pending request data while we're waiting for
the client to receive these data. Now a 5k backend stats page is dumped at
1% CPU over a 10 Mbps link instead of 100%, using 1500 epoll_wait() calls
instead of 80000.

Note that the previous fix (BUG/MEDIUM: stream-int: don't immediately
enable reading when the buffer was reportedly full) is necessary for the
effects of the fix to be noticed since both bugs have the exact same
effect.

This fix must be backported at least as far as 1.5.
src/stats.c