mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-27 15:12:11 +00:00
BUG/MINOR: cli: avoid O(bufsize) parsing cost on pipelined commands
Sending pipelined commands on the CLI using a semi-colon as a delimiter has a cost that grows linearly with the buffer size, because co_getline() is called for each word and looks up a '\n' in the whole buffer while copying its contents into a temporary buffer. This causes huge parsing delays, for example 3s for 100k "show version" versus 110ms if parsed only once for a default 16k buffer. This patch makes use of the new co_getdelim() function to support both an LF and a semi-colon as delimiters so that it's no more needed to parse the whole buffer, and that commands are instantly retrieved. We still need to rely on co_getline() in payload mode as escapes and semi-colons are not used there. It should likely be backported where CLI processing speed matters, but will require to also backport previous patch "MINOR: channel: add new function co_getdelim() to support multiple delimiters". It's worth noting that backporting it without "MEDIUM: cli: yield between each pipelined command" would significantly increase the ratio of disconnections caused by empty request buffers, for the sole reason that the currently slow parsing grants more time to request data to come in. As such it would be better to backport the patch above before taking this one.
This commit is contained in:
parent
c514365317
commit
0011c25144
17
src/cli.c
17
src/cli.c
@ -890,9 +890,20 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
break;
|
||||
}
|
||||
|
||||
/* '- 1' is to ensure a null byte can always be inserted at the end */
|
||||
reql = co_getline(si_oc(si), str,
|
||||
appctx->chunk->size - appctx->chunk->data - 1);
|
||||
/* payload doesn't take escapes nor does it end on semi-colons, so
|
||||
* we use the regular getline. Normal mode however must stop on
|
||||
* LFs and semi-colons that are not prefixed by a backslash. Note
|
||||
* that we reserve one byte at the end to insert a trailing nul byte.
|
||||
*/
|
||||
|
||||
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)
|
||||
reql = co_getline(si_oc(si), str,
|
||||
appctx->chunk->size - appctx->chunk->data - 1);
|
||||
else
|
||||
reql = co_getdelim(si_oc(si), str,
|
||||
appctx->chunk->size - appctx->chunk->data - 1,
|
||||
"\n;", '\\');
|
||||
|
||||
if (reql <= 0) { /* closed or EOL not found */
|
||||
if (reql == 0)
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user