[MEDIUM] introduce pipe pools
A new data type has been added : pipes. Some pre-allocated empty pipes are maintained in a pool for users such as splice which use them a lot for very short times. Pipes are allocated using get_pipe() and released using put_pipe(). Pipes which are released with pending data are immediately killed. The struct pipe is small (16 to 20 bytes) and may even be further reduced by unifying ->data and ->next. It would be nice to have a dedicated cleanup task which would watch for the pipes usage and destroy a few of them from time to time.
This commit is contained in:
parent
1df2470850
commit
982b6e37e4
2
Makefile
2
Makefile
@ -449,7 +449,7 @@ endif
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o src/proto_uxst.o \
|
||||
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
|
||||
src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
|
||||
|
@ -100,7 +100,7 @@ LDFLAGS = -g
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o src/proto_uxst.o \
|
||||
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
|
||||
src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
|
||||
|
@ -97,7 +97,7 @@ LDFLAGS = -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 -mma
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o src/proto_uxst.o \
|
||||
src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
|
||||
src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
|
||||
|
54
include/proto/pipe.h
Normal file
54
include/proto/pipe.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
include/proto/pipe.h
|
||||
Pipe management
|
||||
|
||||
Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation, version 2.1
|
||||
exclusively.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _PROTO_PIPE_H
|
||||
#define _PROTO_PIPE_H
|
||||
|
||||
#include <common/config.h>
|
||||
#include <types/pipe.h>
|
||||
|
||||
extern int pipes_used; /* # of pipes in use (2 fds each) */
|
||||
extern int pipes_free; /* # of pipes unused (2 fds each) */
|
||||
|
||||
/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
|
||||
* left. NULL is returned if a pipe could not be allocated.
|
||||
*/
|
||||
struct pipe *get_pipe();
|
||||
|
||||
/* destroy a pipe, possibly because an error was encountered on it. Its FDs
|
||||
* will be closed and it will not be reinjected into the live pool.
|
||||
*/
|
||||
void kill_pipe(struct pipe *p);
|
||||
|
||||
/* put back a unused pipe into the live pool. If it still has data in it, it is
|
||||
* closed and not reinjected into the live pool. The caller is not allowed to
|
||||
* use it once released.
|
||||
*/
|
||||
void put_pipe(struct pipe *p);
|
||||
|
||||
#endif /* _PROTO_PIPE_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
45
include/types/pipe.h
Normal file
45
include/types/pipe.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
include/types/pipe.h
|
||||
Pipe management.
|
||||
|
||||
Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation, version 2.1
|
||||
exclusively.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _TYPES_PIPE_H
|
||||
#define _TYPES_PIPE_H
|
||||
|
||||
#include <common/config.h>
|
||||
|
||||
/* A pipe is described by its read and write FDs, and the data remaining in it.
|
||||
* The FDs are valid if there are data pending. The user is not allowed to
|
||||
* change the FDs.
|
||||
*/
|
||||
struct pipe {
|
||||
int data; /* number of bytes present in the pipe */
|
||||
int prod; /* FD the producer must write to ; -1 if none */
|
||||
int cons; /* FD the consumer must read from ; -1 if none */
|
||||
struct pipe *next;
|
||||
};
|
||||
|
||||
#endif /* _TYPES_PIPE_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
109
src/pipe.c
Normal file
109
src/pipe.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Pipe management
|
||||
*
|
||||
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/memory.h>
|
||||
|
||||
#include <types/global.h>
|
||||
#include <types/pipe.h>
|
||||
|
||||
struct pool_head *pool2_pipe = NULL;
|
||||
struct pipe *pipes_live = NULL; /* pipes which are still ready to use */
|
||||
int pipes_used = 0; /* # of pipes in use (2 fds each) */
|
||||
int pipes_free = 0; /* # of pipes unused */
|
||||
|
||||
/* allocate memory for the pipes */
|
||||
static void init_pipe()
|
||||
{
|
||||
pool2_pipe = create_pool("pipe", sizeof(struct pipe), MEM_F_SHARED);
|
||||
pipes_used = 0;
|
||||
pipes_free = 0;
|
||||
}
|
||||
|
||||
/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
|
||||
* left. NULL is returned if a pipe could not be allocated.
|
||||
*/
|
||||
struct pipe *get_pipe()
|
||||
{
|
||||
struct pipe *ret;
|
||||
int pipefd[2];
|
||||
|
||||
if (likely(pipes_live)) {
|
||||
ret = pipes_live;
|
||||
pipes_live = pipes_live->next;
|
||||
pipes_free--;
|
||||
pipes_used++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pipes_used >= global.maxpipes)
|
||||
return NULL;
|
||||
|
||||
ret = pool_alloc2(pool2_pipe);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
if (pipe(pipefd) < 0) {
|
||||
pool_free2(pool2_pipe, ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->data = 0;
|
||||
ret->prod = pipefd[1];
|
||||
ret->cons = pipefd[0];
|
||||
ret->next = NULL;
|
||||
pipes_used++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* destroy a pipe, possibly because an error was encountered on it. Its FDs
|
||||
* will be closed and it will not be reinjected into the live pool.
|
||||
*/
|
||||
void kill_pipe(struct pipe *p)
|
||||
{
|
||||
close(p->prod);
|
||||
close(p->cons);
|
||||
pool_free2(pool2_pipe, p);
|
||||
pipes_used--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* put back a unused pipe into the live pool. If it still has data in it, it is
|
||||
* closed and not reinjected into the live pool. The caller is not allowed to
|
||||
* use it once released.
|
||||
*/
|
||||
void put_pipe(struct pipe *p)
|
||||
{
|
||||
if (p->data) {
|
||||
kill_pipe(p);
|
||||
return;
|
||||
}
|
||||
p->next = pipes_live;
|
||||
pipes_live = p;
|
||||
pipes_free++;
|
||||
pipes_used--;
|
||||
}
|
||||
|
||||
|
||||
__attribute__((constructor))
|
||||
static void __pipe_module_init(void)
|
||||
{
|
||||
init_pipe();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
Loading…
Reference in New Issue
Block a user