mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 17:35:49 +08:00
Relays: the size of a splice() pipe chosen at build time
sockmap() and the callbacks' relay each had their own 64K for what a pipe is given at most (MAXSPLICE, CBSPLICE). It is PIPESIZE now, one for both, 64K as before: what a pipe holds unless asked otherwise. Built with -DPIPESIZE=<bytes>, pipes are made that large with F_SETPIPE_SZ (pipenew()); one the system will not make so large is not used, and the data is copied, as when there is no pipe to be had. Measured on ARM and Intel (mix-http, mix-relay), 16K and 32K were slower, 128K and 256K no faster than 64K, which stays the default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
17a5287fce
commit
143158e97f
@ -446,8 +446,6 @@ DONE:
|
|||||||
#define SPLICE_F_NONBLOCK 0x02
|
#define SPLICE_F_NONBLOCK 0x02
|
||||||
#endif
|
#endif
|
||||||
ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
|
ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
|
||||||
/* what a pipe of splice() takes at once, as sockmap()'s MAXSPLICE */
|
|
||||||
#define CBSPLICE 65536
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* One way of the relay: from the side src to dst, through the buffer of
|
/* One way of the relay: from the side src to dst, through the buffer of
|
||||||
@ -621,13 +619,13 @@ static int cbway(struct cbmap *m, struct cbway *w){
|
|||||||
|
|
||||||
/* what was buffered goes first: the pipe is read once it is
|
/* what was buffered goes first: the pipe is read once it is
|
||||||
through */
|
through */
|
||||||
if(!inb && !w->wantbuf && w->left > w->inpipe && !m->term_r[w->src] && !end && w->inpipe < CBSPLICE &&
|
if(!inb && !w->wantbuf && w->left > w->inpipe && !m->term_r[w->src] && !end && w->inpipe < PIPESIZE &&
|
||||||
(rs->ready & (POLLIN | POLLHUP | POLLERR))){
|
(rs->ready & (POLLIN | POLLHUP | POLLERR))){
|
||||||
if(pipe[0] < 0 && pipe2(pipe, O_NONBLOCK) < 0){
|
if(pipe[0] < 0 && pipenew(pipe) < 0){
|
||||||
w->splice = 0;
|
w->splice = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)CBSPLICE - w->inpipe,
|
n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)PIPESIZE - w->inpipe,
|
||||||
w->left - w->inpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
w->left - w->inpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
w->inpipe += n;
|
w->inpipe += n;
|
||||||
|
|||||||
@ -628,6 +628,12 @@ extern struct commands commandhandlers[];
|
|||||||
#define SPLICE_TLS 1
|
#define SPLICE_TLS 1
|
||||||
#define SPLICE_TLSPENDING 2
|
#define SPLICE_TLSPENDING 2
|
||||||
extern int (*splicetls)(struct clientparam *param, SOCKET s);
|
extern int (*splicetls)(struct clientparam *param, SOCKET s);
|
||||||
|
/* what a pipe of splice() is given at most: 64K, what a pipe holds;
|
||||||
|
built with -DPIPESIZE=<bytes>, pipes are made that large */
|
||||||
|
#ifndef PIPESIZE
|
||||||
|
#define PIPESIZE 65536
|
||||||
|
#endif
|
||||||
|
int pipenew(int p[2]);
|
||||||
#define mapsocket(a,b) ((a->srv->usesplice && !a->nosplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,a->srv->usesplice):sockmap(a,b,0))
|
#define mapsocket(a,b) ((a->srv->usesplice && !a->nosplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,a->srv->usesplice):sockmap(a,b,0))
|
||||||
#else
|
#else
|
||||||
#define mapsocket(a,b) sockmap(a,b, 0)
|
#define mapsocket(a,b) sockmap(a,b, 0)
|
||||||
|
|||||||
@ -36,12 +36,29 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
|
|||||||
#define SPLICE_F_GIFT 0x08
|
#define SPLICE_F_GIFT 0x08
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_SETPIPE_SZ
|
||||||
|
#define F_SETPIPE_SZ 1031
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAXSPLICE 65536
|
|
||||||
/* splice() refuses a kernel TLS record that is not data: EINVAL, or EIO
|
/* splice() refuses a kernel TLS record that is not data: EINVAL, or EIO
|
||||||
and EBADMSG on some kernels */
|
and EBADMSG on some kernels */
|
||||||
#define SPLICEREFUSED(e) ((e) == EINVAL || (e) == EIO || (e) == EBADMSG)
|
#define SPLICEREFUSED(e) ((e) == EINVAL || (e) == EIO || (e) == EBADMSG)
|
||||||
|
|
||||||
|
/* A pipe for splice(), nonblocking, of PIPESIZE: -1 if there is none to be
|
||||||
|
had, or not of that size. */
|
||||||
|
int pipenew(int p[2]){
|
||||||
|
if(pipe2(p, O_NONBLOCK) < 0) return -1;
|
||||||
|
#if PIPESIZE != 65536
|
||||||
|
if(fcntl(p[0], F_SETPIPE_SZ, PIPESIZE) < 0){
|
||||||
|
close(p[0]);
|
||||||
|
close(p[1]);
|
||||||
|
p[0] = p[1] = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* With SPLICE_AUTO, when a direction allowed to splice actually does
|
/* With SPLICE_AUTO, when a direction allowed to splice actually does
|
||||||
(without it, an allowed direction always does).
|
(without it, an allowed direction always does).
|
||||||
A body of known length is spliced if at least splicemin of it is left
|
A body of known length is spliced if at least splicemin of it is left
|
||||||
@ -391,7 +408,7 @@ log("done send to client from buf");
|
|||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("send to server from pipe");
|
log("send to server from pipe");
|
||||||
#endif
|
#endif
|
||||||
res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(PIPESIZE, inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||||
/* from a pipe holding data: the socket is full */
|
/* from a pipe holding data: the socket is full */
|
||||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->remsock, POLLOUT);
|
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->remsock, POLLOUT);
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
@ -430,7 +447,7 @@ log(logbuf);
|
|||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("send to client from pipe");
|
log("send to client from pipe");
|
||||||
#endif
|
#endif
|
||||||
res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(PIPESIZE, inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||||
/* from a pipe holding data: the socket is full */
|
/* from a pipe holding data: the socket is full */
|
||||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->clisock, POLLOUT);
|
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->clisock, POLLOUT);
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
@ -462,7 +479,7 @@ log(logbuf);
|
|||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("read from client to pipe");
|
log("read from client to pipe");
|
||||||
#endif
|
#endif
|
||||||
if(pipecli[0] < 0 && pipe2(pipecli, O_NONBLOCK) < 0){
|
if(pipecli[0] < 0 && pipenew(pipecli) < 0){
|
||||||
/* no pipe to be had: copy instead */
|
/* no pipe to be had: copy instead */
|
||||||
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
||||||
if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1;
|
if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1;
|
||||||
@ -479,7 +496,7 @@ log("read from client to pipe");
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
errno = 0;
|
errno = 0;
|
||||||
res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)MAXSPLICE - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)PIPESIZE - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("client to pipe splice finished\n");
|
log("client to pipe splice finished\n");
|
||||||
#if WITHLOG > 1
|
#if WITHLOG > 1
|
||||||
@ -521,7 +538,7 @@ log("done read from client to pipe");
|
|||||||
else if(++streakcli > splicestreak) wantbufcli = 1;
|
else if(++streakcli > splicestreak) wantbufcli = 1;
|
||||||
}
|
}
|
||||||
inclientpipe += res;
|
inclientpipe += res;
|
||||||
if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0;
|
if(inclientpipe >= PIPESIZE) TOCLIENTPIPE = 0;
|
||||||
needaction = 0;
|
needaction = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -530,7 +547,7 @@ log("done read from client to pipe");
|
|||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("read from server to pipe\n");
|
log("read from server to pipe\n");
|
||||||
#endif
|
#endif
|
||||||
if(pipesrv[0] < 0 && pipe2(pipesrv, O_NONBLOCK) < 0){
|
if(pipesrv[0] < 0 && pipenew(pipesrv) < 0){
|
||||||
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
||||||
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -544,7 +561,7 @@ log("read from server to pipe\n");
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
errno = 0;
|
errno = 0;
|
||||||
res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(MAXSPLICE - inserverpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(PIPESIZE - inserverpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("server to pipe splice finished\n");
|
log("server to pipe splice finished\n");
|
||||||
#if WITHLOG > 1
|
#if WITHLOG > 1
|
||||||
@ -586,7 +603,7 @@ log("done read from server to pipe\n");
|
|||||||
param->nreads++;
|
param->nreads++;
|
||||||
param->statssrv64 += res;
|
param->statssrv64 += res;
|
||||||
inserverpipe += res;
|
inserverpipe += res;
|
||||||
if(inserverpipe >= MAXSPLICE) TOSERVERPIPE = 0;
|
if(inserverpipe >= PIPESIZE) TOSERVERPIPE = 0;
|
||||||
if(param->bandlimfunc) {
|
if(param->bandlimfunc) {
|
||||||
int sl1;
|
int sl1;
|
||||||
sl1 = (*param->bandlimfunc)(param, res, 0);
|
sl1 = (*param->bandlimfunc)(param, res, 0);
|
||||||
@ -876,7 +893,7 @@ log("server terminated connection");
|
|||||||
// }
|
// }
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
{
|
{
|
||||||
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < MAXSPLICE){
|
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < PIPESIZE){
|
||||||
if(!after){
|
if(!after){
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("wait writing to client pipe");
|
log("wait writing to client pipe");
|
||||||
@ -916,7 +933,7 @@ log("ready reading from client pipe");
|
|||||||
}
|
}
|
||||||
fdsc++;
|
fdsc++;
|
||||||
}
|
}
|
||||||
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < MAXSPLICE){
|
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < PIPESIZE){
|
||||||
if(!after){
|
if(!after){
|
||||||
#ifdef WITHLOG
|
#ifdef WITHLOG
|
||||||
log("wait writing to server pipe");
|
log("wait writing to server pipe");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user