mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-07 01:31:35 +00:00
[MEDIUM] http: revert to use a swap buffer for realignment
The bounce realign function was algorithmically good but as expected it was not cache-friendly. Using it with large requests caused so many cache thrashing that the function itself could drain 70% of the total CPU time for only 0.5% of the calls ! Revert back to a standard memcpy() using a specially allocated swap buffer. We're now back to 2M req/s on pipelined requests.
This commit is contained in:
parent
2465779459
commit
8096de9a99
@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
include/types/global.h
|
* include/types/global.h
|
||||||
Global variables.
|
* Global variables.
|
||||||
|
*
|
||||||
Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
|
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
||||||
|
*
|
||||||
This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation, version 2.1
|
* License as published by the Free Software Foundation, version 2.1
|
||||||
exclusively.
|
* exclusively.
|
||||||
|
*
|
||||||
This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TYPES_GLOBAL_H
|
#ifndef _TYPES_GLOBAL_H
|
||||||
#define _TYPES_GLOBAL_H
|
#define _TYPES_GLOBAL_H
|
||||||
@ -103,6 +103,7 @@ extern int relative_pid; /* process id starting at 1 */
|
|||||||
extern int actconn; /* # of active sessions */
|
extern int actconn; /* # of active sessions */
|
||||||
extern int listeners;
|
extern int listeners;
|
||||||
extern char trash[BUFSIZE];
|
extern char trash[BUFSIZE];
|
||||||
|
extern char *swap_buffer;
|
||||||
extern const int zero;
|
extern const int zero;
|
||||||
extern const int one;
|
extern const int one;
|
||||||
extern const struct linger nolinger;
|
extern const struct linger nolinger;
|
||||||
|
@ -138,6 +138,11 @@ static int oldpids_sig; /* use USR1 or TERM */
|
|||||||
/* this is used to drain data, and as a temporary buffer for sprintf()... */
|
/* this is used to drain data, and as a temporary buffer for sprintf()... */
|
||||||
char trash[BUFSIZE];
|
char trash[BUFSIZE];
|
||||||
|
|
||||||
|
/* this buffer is always the same size as standard buffers and is used for
|
||||||
|
* swapping data inside a buffer.
|
||||||
|
*/
|
||||||
|
char *swap_buffer = NULL;
|
||||||
|
|
||||||
const int zero = 0;
|
const int zero = 0;
|
||||||
const int one = 1;
|
const int one = 1;
|
||||||
const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
|
const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
|
||||||
@ -653,6 +658,8 @@ void init(int argc, char **argv)
|
|||||||
if (global.nbproc < 1)
|
if (global.nbproc < 1)
|
||||||
global.nbproc = 1;
|
global.nbproc = 1;
|
||||||
|
|
||||||
|
swap_buffer = (char *)calloc(1, global.tune.bufsize);
|
||||||
|
|
||||||
fdinfo = (struct fdinfo *)calloc(1,
|
fdinfo = (struct fdinfo *)calloc(1,
|
||||||
sizeof(struct fdinfo) * (global.maxsock));
|
sizeof(struct fdinfo) * (global.maxsock));
|
||||||
fdtab = (struct fdtab *)calloc(1,
|
fdtab = (struct fdtab *)calloc(1,
|
||||||
|
@ -2259,14 +2259,21 @@ void http_buffer_heavy_realign(struct buffer *buf, struct http_msg *msg)
|
|||||||
|
|
||||||
/* two possible cases :
|
/* two possible cases :
|
||||||
* - the buffer is in one contiguous block, we move it in-place
|
* - the buffer is in one contiguous block, we move it in-place
|
||||||
* - the buffer is in two blocks, we move it via the trash
|
* - the buffer is in two blocks, we move it via the swap_buffer
|
||||||
*/
|
*/
|
||||||
if (buf->l) {
|
if (buf->l) {
|
||||||
if (buf->r <= buf->w)
|
int block1 = buf->l;
|
||||||
|
int block2 = 0;
|
||||||
|
if (buf->r <= buf->w) {
|
||||||
/* non-contiguous block */
|
/* non-contiguous block */
|
||||||
buffer_bounce_realign(buf);
|
block1 = buf->data + buf->size - buf->w;
|
||||||
else
|
block2 = buf->r - buf->data;
|
||||||
memmove(buf->data, buf->w, buf->l);
|
}
|
||||||
|
if (block2)
|
||||||
|
memcpy(swap_buffer, buf->data, block2);
|
||||||
|
memmove(buf->data, buf->w, block1);
|
||||||
|
if (block2)
|
||||||
|
memcpy(buf->data + block1, swap_buffer, block2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adjust all known pointers */
|
/* adjust all known pointers */
|
||||||
|
Loading…
Reference in New Issue
Block a user