mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
OPTIM: channel: speed up co_getline()'s search of the end of line
Previously, co_getline() was essentially used for occasional parsing in peers's banner or Lua, so it could afford to read one character at a time. However now it's also used on the TCP log path, where it can consume up to 40% CPU as mentioned in GH issue #2731. Let's speed it up by using memchr() to look for the LF, and copying the data at once using memcpy(). Previously it would take 2.44s to consume 1 GB of log on a single thread of a Core i7-8650U, now it takes 1.56s (-36%).
This commit is contained in:
parent
7caf073faa
commit
11051ed9c7
@ -324,7 +324,7 @@ int co_getword(const struct channel *chn, char *str, int len, char sep)
|
||||
int co_getline(const struct channel *chn, char *str, int len)
|
||||
{
|
||||
int ret, max;
|
||||
char *p;
|
||||
size_t ofs;
|
||||
|
||||
ret = 0;
|
||||
max = len;
|
||||
@ -336,20 +336,30 @@ int co_getline(const struct channel *chn, char *str, int len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = co_head(chn);
|
||||
|
||||
if (max > co_data(chn)) {
|
||||
max = co_data(chn);
|
||||
str[max-1] = 0;
|
||||
}
|
||||
while (max) {
|
||||
*str++ = *p;
|
||||
ret++;
|
||||
max--;
|
||||
|
||||
if (*p == '\n')
|
||||
ofs = 0;
|
||||
|
||||
while (max) {
|
||||
size_t contig = b_contig_data(&chn->buf, ofs);
|
||||
size_t len = MIN(max, contig);
|
||||
const char *beg = b_peek(&chn->buf, ofs);
|
||||
const char *lf = memchr(beg, '\n', len);
|
||||
|
||||
if (lf) /* take the LF with it before stopping */
|
||||
len = lf + 1 - beg;
|
||||
|
||||
memcpy(str, beg, len);
|
||||
ret += len;
|
||||
str += len;
|
||||
ofs += len;
|
||||
max -= len;
|
||||
|
||||
if (lf)
|
||||
break;
|
||||
p = b_next(&chn->buf, p);
|
||||
}
|
||||
if (ret > 0 && ret < len &&
|
||||
(ret < co_data(chn) || channel_may_recv(chn)) &&
|
||||
|
Loading…
Reference in New Issue
Block a user