Disable splice support
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run

This commit is contained in:
Vladimir Dubrovin 2026-08-01 09:38:49 +03:00
parent 92d3b08dd2
commit 7b85f6a684
6 changed files with 19 additions and 46 deletions

View File

@ -51,7 +51,7 @@ option(3PROXY_USE_OPENSSL "Enable TLS/SSL support via OpenSSL (fallback when wol
option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" ON) option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" ON)
option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON) option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON)
option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF) option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF)
option(3PROXY_USE_SPLICE "Use Linux splice() for zero-copy (Linux only)" ON) option(3PROXY_USE_SPLICE "Build Linux splice() support, slower than read/write for most traffic (Linux only)" OFF)
option(3PROXY_USE_POLL "Use poll() instead of select() (Unix only)" ON) option(3PROXY_USE_POLL "Use poll() instead of select() (Unix only)" ON)
option(3PROXY_USE_WSAPOLL "Use WSAPoll instead of select() (Windows only)" ON) option(3PROXY_USE_WSAPOLL "Use WSAPoll instead of select() (Windows only)" ON)
option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON) option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON)

View File

@ -3,6 +3,10 @@
# #
# add -DWITH_ODBC to CFLAGS and -lodbc to LIBS to compile with ODBC # add -DWITH_ODBC to CFLAGS and -lodbc to LIBS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers. # library support. Add -DSAFESQL for poorely written ODBC library / drivers.
#
# Linux splice() support is not built by default, it is slower than the
# read/write path for most traffic. Add -DWITHSPLICE to CFLAGS to build it,
# it must additionally be enabled per service with the -s option.
BUILDDIR = ../bin/ BUILDDIR = ../bin/
PREFIX ?= 3proxy_ PREFIX ?= 3proxy_
@ -10,7 +14,7 @@ CRYPT_PREFIX ?= $(PREFIX)
CC ?= gcc CC ?= gcc
CFLAGS ?= -O3 -flto CFLAGS ?= -O3 -flto
CFLAGS += -fno-strict-aliasing -c -pthread -DWITHSPLICE -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN CFLAGS += -fno-strict-aliasing -c -pthread -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN
COUT = -o COUT = -o
LN ?= ${CC} LN ?= ${CC}
DCFLAGS ?= -fPIC DCFLAGS ?= -fPIC

View File

@ -30,10 +30,7 @@ Each connected client requires:
<ul> <ul>
<li>1 thread (process) <li>1 thread (process)
<li>2 sockets (file descriptors). For FTP, 4 sockets are required. <li>2 sockets (file descriptors). For FTP, 4 sockets are required.
<br>Under Linux since 0.9, splice() is used. It's much more efficient but requires <br>Up to 128K of kernel buffer memory. This is the theoretical maximum; actual numbers depend on connection quality and traffic amount.
<br>2 sockets (file descriptors) + 2 pipes (file descriptors) = 4 file descriptors.
<br>For FTP with splice(), 4 sockets and 2 pipes are required.
<br>Up to 128K (up to 256K in the case of splice()) of kernel buffer memory. This is the theoretical maximum; actual numbers depend on connection quality and traffic amount.
<br>1 additional socket (file descriptor) during name resolution for non-cached names <br>1 additional socket (file descriptor) during name resolution for non-cached names
<br>1 additional socket during authentication or logging for RADIUS authentication or logging. <br>1 additional socket during authentication or logging for RADIUS authentication or logging.
<li>1 ephemeral port (3 ephemeral ports for FTP connections). <li>1 ephemeral port (3 ephemeral ports for FTP connections).
@ -90,15 +87,6 @@ Available options are system-dependent.
If 3proxy is used in a VPS environment, there can be additional limitations. If 3proxy is used in a VPS environment, there can be additional limitations.
For example, kernel resources, system CPU usage, and IOCTLs can be limited differently, and this can become a bottleneck. For example, kernel resources, system CPU usage, and IOCTLs can be limited differently, and this can become a bottleneck.
Since 0.9-devel, 3proxy uses splice() by default on Linux. splice() prevents network traffic from being copied from
kernel space to the 3proxy process and generally increases throughput, especially in the case of high-volume traffic. This is especially
true for virtual environments (it can improve throughput up to 10 times) unless there are additional kernel limitations.
Since some work is moved to the kernel, it requires up to 2 times more kernel resources in terms of CPU, memory, and IOCTLs.
If your hosting additionally limits kernel resources (you can see this as nearly 100% CPU usage without any real CPU activity for
any application performing IOCTLs), use the -s0 option to disable splice() usage for a given service, e.g.:
<pre>
socks -s0
</pre>
<h4>Extending the Ephemeral Port Range</h4> <h4>Extending the Ephemeral Port Range</h4>
@ -268,24 +256,6 @@ sets TCP_NODELAY for client (oc) and server (os) connections.
<p>Do not use TCP_NODELAY on slow connections with high delays when <p>Do not use TCP_NODELAY on slow connections with high delays when
connection bandwidth is a bottleneck. connection bandwidth is a bottleneck.
<h4>Use Splice to Speed Up Large Data Amount Transfers</h4>
splice() allows copying data between connections without copying to the process
address space. It can speed up the proxy on high-bandwidth connections if most
connections require large data transfers. Splice is enabled by default on Linux
since 0.9; "-s0" disables splice usage. Example:
<pre>
proxy -s0
</pre>
Splice is only available on Linux. Splice requires more system buffers and file descriptors
and produces more IOCTLs but reduces process memory and overall CPU usage.
Disable splice if there are a lot of short-lived connections with no bandwidth
requirements.
<p>Use splice only on high-speed connections (e.g., 10GbE) when the processor, memory speed, or
system bus are bottlenecks.
<p>TCP_NODELAY and splice are not contrary to each other and should be combined on
high-speed connections.
<h4>Add Grace Delay to Reduce System Calls</h4> <h4>Add Grace Delay to Reduce System Calls</h4>
<pre>proxy -g8000,3,10</pre> <pre>proxy -g8000,3,10</pre>
@ -294,7 +264,7 @@ the minimal number of packets in the same direction to apply the algorithm,
and the last value is the delay added after polling and prior to reading data. and the last value is the delay added after polling and prior to reading data.
The example above adds a 10-millisecond delay before reading data if the average The example above adds a 10-millisecond delay before reading data if the average
polling size is below 8000 bytes and 3 read operations have been made in the same polling size is below 8000 bytes and 3 read operations have been made in the same
direction. It's especially useful with splice. <pre>logdump 1 1</pre> is useful direction. <pre>logdump 1 1</pre> is useful
to see how grace delays work; choose a delay value to avoid filling the read to see how grace delays work; choose a delay value to avoid filling the read
pipe/buffer (typically 64K) but keep the request sizes close to the chosen average pipe/buffer (typically 64K) but keep the request sizes close to the chosen average
on large file uploads/downloads. on large file uploads/downloads.

View File

@ -188,9 +188,16 @@ any protocol-specific data.
.br .br
.B -g(\fIGRACE_TRAFF\fB,\fIGRACE_NUM\fB,\fIGRACE_DELAY\fR) .B -g(\fIGRACE_TRAFF\fB,\fIGRACE_NUM\fB,\fIGRACE_DELAY\fR)
delay GRACE_DELAY milliseconds before polling if average polling size is below GRACE_TRAFF bytes and GRACE_NUM read operations in a single direction are detected within 1 second. Useful to minimize polling delay GRACE_DELAY milliseconds before polling if average polling size is below GRACE_TRAFF bytes and GRACE_NUM read operations in a single direction are detected within 1 second. Useful to minimize polling
.br
.B -s .B -s
(for admin) secure, allow only secure operations, currently only traffic counters (for admin) secure, allow only secure operations, currently only traffic counters
view without ability to reset. view without ability to reset.
.br
(for TCP services, Linux) enable splice(). splice() is not built by default and
is disabled even when built, because current Linux does not implement
SPLICE_F_MOVE, so no real zero-copy takes place and the read/write path is faster
for most traffic. Rebuild with -DWITHSPLICE to make -s available, -s0 disables it
explicitly.
.br .br
(for dnspr) simple, do not use resolver and 3proxy cache, always use external DNS server. (for dnspr) simple, do not use resolver and 3proxy cache, always use external DNS server.
.br .br

View File

@ -35,7 +35,6 @@ void * dnsprchild(struct clientparam* param) {
if(!(bbuf = malloc(BUFSIZE+2))){ if(!(bbuf = malloc(BUFSIZE+2))){
param->srv->fds.events = POLLIN;
RETURN (21); RETURN (21);
} }
buf = bbuf+2; buf = bbuf+2;
@ -59,7 +58,6 @@ void * dnsprchild(struct clientparam* param) {
#else #else
param->clisock = param->srv->srvsock; param->clisock = param->srv->srvsock;
#endif #endif
param->srv->fds.events = POLLIN;
if(i < 0) { if(i < 0) {
RETURN(813); RETURN(813);

View File

@ -311,7 +311,7 @@ int MODULEMAINFUNC (int argc, char** argv){
" -De(DEVICENAME) bind external interface to device, e.g. eth1\n" " -De(DEVICENAME) bind external interface to device, e.g. eth1\n"
#endif #endif
#ifdef WITHSPLICE #ifdef WITHSPLICE
" -s Use splice() - faster proxing, but no filtering for data\n" " -s Use splice() - no filtering for data, off by default\n"
#endif #endif
"-g(GRACE_TRAFF,GRACE_NUM,GRACE_DELAY) - delay GRACE_DELAY milliseconds before polling if average polling size below GRACE_TRAFF bytes and GRACE_NUM read operations in single directions are detected within 1 second to minimize polling\n" "-g(GRACE_TRAFF,GRACE_NUM,GRACE_DELAY) - delay GRACE_DELAY milliseconds before polling if average polling size below GRACE_TRAFF bytes and GRACE_NUM read operations in single directions are detected within 1 second to minimize polling\n"
" -fFORMAT logging format (see documentation)\n" " -fFORMAT logging format (see documentation)\n"
@ -586,7 +586,7 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.s_option = 1 + atoi(argv[i]+2); srv.s_option = 1 + atoi(argv[i]+2);
#ifdef WITHSPLICE #ifdef WITHSPLICE
else else
if(*(argv[i]+2)) srv.usesplice = atoi(argv[i]+2); srv.usesplice = *(argv[i]+2)? atoi(argv[i]+2) : 1;
#endif #endif
break; break;
case 'o': case 'o':
@ -956,13 +956,7 @@ int MODULEMAINFUNC (int argc, char** argv){
} }
if (iscbc) break; if (iscbc) break;
if (conf.paused != srv.paused) break; if (conf.paused != srv.paused) break;
if (srv.fds.events & POLLIN) { error = srv.so._poll(srv.so.state, &srv.fds, 1, 1000);
error = srv.so._poll(srv.so.state, &srv.fds, 1, 1000);
}
else {
usleep(SLEEPTIME);
continue;
}
if (error >= 1) break; if (error >= 1) break;
if (error == 0) continue; if (error == 0) continue;
if (errno != EAGAIN && errno != EINTR) { if (errno != EAGAIN && errno != EINTR) {
@ -1225,7 +1219,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
srv->saved_nsfd = srv->i_nsfd = srv->o_nsfd = -1; srv->saved_nsfd = srv->i_nsfd = srv->o_nsfd = -1;
#endif #endif
#ifdef WITHSPLICE #ifdef WITHSPLICE
srv->usesplice = 1; srv->usesplice = 0;
#endif #endif
memset(param, 0, sizeof(struct clientparam)); memset(param, 0, sizeof(struct clientparam));
param->srv = srv; param->srv = srv;