mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-28 00:20:56 +00:00
[OPTIM] halog: make fgets parse more bytes by blocks
By adding a "landing area" at the end of the buffer, it becomes safe to parse more bytes at once. On 32-bit this makes fgets run about 4% faster but it does not save anything on 64-bit.
This commit is contained in:
parent
e8c7ecc2dd
commit
31a02e9c5b
@ -58,7 +58,7 @@ static inline unsigned long long has_zero64(unsigned long long x)
|
|||||||
#define FGETS2_BUFSIZE (256*1024)
|
#define FGETS2_BUFSIZE (256*1024)
|
||||||
const char *fgets2(FILE *stream)
|
const char *fgets2(FILE *stream)
|
||||||
{
|
{
|
||||||
static char buffer[FGETS2_BUFSIZE + 9]; // +9 to have zeroes past the end
|
static char buffer[FGETS2_BUFSIZE + 68];
|
||||||
static char *end = buffer;
|
static char *end = buffer;
|
||||||
static char *line = buffer;
|
static char *line = buffer;
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ const char *fgets2(FILE *stream)
|
|||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (next <= (end-12)) {
|
if (next <= end) {
|
||||||
/* max 3 bytes tested here */
|
/* max 3 bytes tested here */
|
||||||
while ((((unsigned long)next) & 3) && *next != '\n')
|
while ((((unsigned long)next) & 3) && *next != '\n')
|
||||||
next++;
|
next++;
|
||||||
@ -115,8 +115,8 @@ const char *fgets2(FILE *stream)
|
|||||||
if (!has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
|
if (!has_zero(*(unsigned int *)next ^ 0x0A0A0A0AU))
|
||||||
next += 4;
|
next += 4;
|
||||||
|
|
||||||
/* we finish if needed. Note that next might be slightly higher
|
/* We finish if needed : if <next> is below <end>, it means we
|
||||||
* than end here because we might have gone past it above.
|
* found an LF in one of the 4 following bytes.
|
||||||
*/
|
*/
|
||||||
while (next < end) {
|
while (next < end) {
|
||||||
if (*next == '\n') {
|
if (*next == '\n') {
|
||||||
@ -131,7 +131,8 @@ const char *fgets2(FILE *stream)
|
|||||||
|
|
||||||
/* we found an incomplete line. First, let's move the
|
/* we found an incomplete line. First, let's move the
|
||||||
* remaining part of the buffer to the beginning, then
|
* remaining part of the buffer to the beginning, then
|
||||||
* try to complete the buffer with a new read.
|
* try to complete the buffer with a new read. We can't
|
||||||
|
* rely on <next> anymore because it went past <end>.
|
||||||
*/
|
*/
|
||||||
if (line > buffer) {
|
if (line > buffer) {
|
||||||
if (end != line)
|
if (end != line)
|
||||||
@ -156,6 +157,7 @@ const char *fgets2(FILE *stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end += ret;
|
end += ret;
|
||||||
|
*end = '\n'; /* make parser stop ASAP */
|
||||||
/* search for '\n' again */
|
/* search for '\n' again */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ static inline unsigned int has_zero(unsigned int x)
|
|||||||
#define FGETS2_BUFSIZE (256*1024)
|
#define FGETS2_BUFSIZE (256*1024)
|
||||||
const char *fgets2(FILE *stream)
|
const char *fgets2(FILE *stream)
|
||||||
{
|
{
|
||||||
static char buffer[FGETS2_BUFSIZE + 5];
|
static char buffer[FGETS2_BUFSIZE + 32];
|
||||||
static char *end = buffer;
|
static char *end = buffer;
|
||||||
static char *line = buffer;
|
static char *line = buffer;
|
||||||
|
|
||||||
@ -64,8 +64,10 @@ const char *fgets2(FILE *stream)
|
|||||||
while (next < end && (((unsigned long)next) & 3) && *next != '\n')
|
while (next < end && (((unsigned long)next) & 3) && *next != '\n')
|
||||||
next++;
|
next++;
|
||||||
|
|
||||||
/* now next is multiple of 4 or equal to end */
|
/* Now next is multiple of 4 or equal to end. We know we can safely
|
||||||
while (next <= (end-32)) {
|
* read up to 32 bytes past end if needed because they're allocated.
|
||||||
|
*/
|
||||||
|
while (next < end) {
|
||||||
if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
|
if (has_zero(*(unsigned int *)next ^ 0x0A0A0A0A))
|
||||||
break;
|
break;
|
||||||
next += 4;
|
next += 4;
|
||||||
@ -92,8 +94,8 @@ const char *fgets2(FILE *stream)
|
|||||||
next += 4;
|
next += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we finish if needed. Note that next might be slightly higher
|
/* We finish if needed : if <next> is below <end>, it means we
|
||||||
* than end here because we might have gone past it above.
|
* found an LF in one of the 4 following bytes.
|
||||||
*/
|
*/
|
||||||
while (next < end) {
|
while (next < end) {
|
||||||
if (*next == '\n') {
|
if (*next == '\n') {
|
||||||
@ -108,7 +110,8 @@ const char *fgets2(FILE *stream)
|
|||||||
|
|
||||||
/* we found an incomplete line. First, let's move the
|
/* we found an incomplete line. First, let's move the
|
||||||
* remaining part of the buffer to the beginning, then
|
* remaining part of the buffer to the beginning, then
|
||||||
* try to complete the buffer with a new read.
|
* try to complete the buffer with a new read. We can't
|
||||||
|
* rely on <next> anymore because it went past <end>.
|
||||||
*/
|
*/
|
||||||
if (line > buffer) {
|
if (line > buffer) {
|
||||||
if (end != line)
|
if (end != line)
|
||||||
@ -133,6 +136,7 @@ const char *fgets2(FILE *stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end += ret;
|
end += ret;
|
||||||
|
*end = '\n'; /* make parser stop ASAP */
|
||||||
/* search for '\n' again */
|
/* search for '\n' again */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user