1
0
mirror of https://github.com/golang/go synced 2024-11-26 22:21:27 -07:00
go/src/net
Andrei Tudor Călin f2316c2789 net: add support for splice(2) in (*TCPConn).ReadFrom on Linux
This change adds support for the splice system call on Linux,
for the purpose of optimizing (*TCPConn).ReadFrom by reducing
copies of data from and to userspace. It does so by creating a
temporary pipe and splicing data from the source connection to the
pipe, then from the pipe to the destination connection. The pipe
serves as an in-kernel buffer for the data transfer.

No new API is added to package net, but a new Splice function is
added to package internal/poll, because using splice requires help
from the network poller. Users of the net package should benefit
from the change transparently.

This change only enables the optimization if the Reader in ReadFrom
is a TCP connection. Since splice is a more general interface, it
could, in theory, also be enabled if the Reader were a unix socket,
or the read half of a pipe.

However, benchmarks show that enabling it for unix sockets is most
likely not a net performance gain. The tcp <- unix case is also
fairly unlikely to be used very much by users of package net.

Enabling the optimization for pipes is also problematic from an
implementation perspective, since package net cannot easily get at
the *poll.FD of an *os.File. A possible solution to this would be
to dup the pipe file descriptor, register the duped descriptor with
the network poller, and work on that *poll.FD instead of the original.
However, this seems too intrusive, so it has not been done. If there
was a clean way to do it, it would probably be worth doing, since
splicing from a pipe to a socket can be done directly.

Therefore, this patch only enables the optimization for what is likely
the most common use case: tcp <- tcp.

The following benchmark compares the performance of the previous
userspace genericReadFrom code path to the new optimized code path.
The sub-benchmarks represent chunk sizes used by the writer on the
other end of the Reader passed to ReadFrom.

benchmark                          old ns/op     new ns/op     delta
BenchmarkTCPReadFrom/1024-4        4727          4954          +4.80%
BenchmarkTCPReadFrom/2048-4        4389          4301          -2.01%
BenchmarkTCPReadFrom/4096-4        4606          4534          -1.56%
BenchmarkTCPReadFrom/8192-4        5219          4779          -8.43%
BenchmarkTCPReadFrom/16384-4       8708          8008          -8.04%
BenchmarkTCPReadFrom/32768-4       16349         14973         -8.42%
BenchmarkTCPReadFrom/65536-4       35246         27406         -22.24%
BenchmarkTCPReadFrom/131072-4      72920         52382         -28.17%
BenchmarkTCPReadFrom/262144-4      149311        95094         -36.31%
BenchmarkTCPReadFrom/524288-4      306704        181856        -40.71%
BenchmarkTCPReadFrom/1048576-4     674174        357406        -46.99%

benchmark                          old MB/s     new MB/s     speedup
BenchmarkTCPReadFrom/1024-4        216.62       206.69       0.95x
BenchmarkTCPReadFrom/2048-4        466.61       476.08       1.02x
BenchmarkTCPReadFrom/4096-4        889.09       903.31       1.02x
BenchmarkTCPReadFrom/8192-4        1569.40      1714.06      1.09x
BenchmarkTCPReadFrom/16384-4       1881.42      2045.84      1.09x
BenchmarkTCPReadFrom/32768-4       2004.18      2188.41      1.09x
BenchmarkTCPReadFrom/65536-4       1859.38      2391.25      1.29x
BenchmarkTCPReadFrom/131072-4      1797.46      2502.21      1.39x
BenchmarkTCPReadFrom/262144-4      1755.69      2756.68      1.57x
BenchmarkTCPReadFrom/524288-4      1709.42      2882.98      1.69x
BenchmarkTCPReadFrom/1048576-4     1555.35      2933.84      1.89x

Fixes #10948

Change-Id: I3ce27f21f7adda8b696afdc48a91149998ae16a5
Reviewed-on: https://go-review.googlesource.com/107715
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-04-24 14:14:56 +00:00
..
http net/http: remove unnecessary parameter type 2018-04-22 17:30:54 +00:00
internal/socktest net, internal/poll, net/internal/socktest: use SOCK_{CLOEXEC,NONBLOCK} accept4/socket flags on OpenBSD 2018-02-26 16:59:38 +00:00
mail all: use strings.Builder instead of bytes.Buffer where appropriate 2018-03-26 23:05:53 +00:00
rpc net/rpc: unlock client.mutex as early as possible 2018-04-06 14:47:39 +00:00
smtp net/smtp: return error from SendMail when required AUTH not available 2018-02-13 18:38:05 +00:00
testdata
textproto net/textproto: reject all headers with a leading space 2017-11-27 20:26:19 +00:00
url net/url: update docs to match renamed receiver 2018-04-12 17:39:23 +00:00
addrselect_test.go net: disable RFC 6724 Rule 9 for IPv4 addresses 2017-01-06 20:55:48 +00:00
addrselect.go net: disable RFC 6724 Rule 9 for IPv4 addresses 2017-01-06 20:55:48 +00:00
cgo_android.go
cgo_bsd.go
cgo_linux.go
cgo_netbsd.go
cgo_openbsd.go
cgo_resnew.go
cgo_resold.go
cgo_socknew.go
cgo_sockold.go
cgo_solaris.go
cgo_stub.go
cgo_unix_test.go net: avoid race on test hooks with DNS goroutines 2017-12-08 05:12:13 +00:00
cgo_unix.go {net,os/user,plugin}: eliminate unnecessary C round-trips 2017-08-17 18:14:16 +00:00
cgo_windows.go
conf_netcgo.go
conf_test.go net: make Resolver.PreferGo work more as documented 2018-03-16 07:02:38 +00:00
conf.go net: treat a nil *Resolver as a zero one, as documented 2018-03-19 17:01:23 +00:00
conn_test.go
dial_test.go net: ignore TestDialerLocalAddr timeout failures on Darwin 2018-01-03 19:46:56 +00:00
dial_unix_test.go net: map context errors from aborted dial to internal net package errors 2018-03-29 23:39:53 +00:00
dial.go net: update documentation on Listen and ListenPacket 2017-06-22 08:31:13 +00:00
dnsclient_test.go net: use golang.org/x/net/dns/dnsmessage for DNS resolution 2018-03-15 04:18:11 +00:00
dnsclient_unix_test.go net: use golang.org/x/net/dns/dnsmessage for DNS resolution 2018-03-15 04:18:11 +00:00
dnsclient_unix.go net: treat a nil *Resolver as a zero one, as documented 2018-03-19 17:01:23 +00:00
dnsclient.go net: use golang.org/x/net/dns/dnsmessage for DNS resolution 2018-03-15 04:18:11 +00:00
dnsconfig_unix_test.go
dnsconfig_unix.go
dnsname_test.go
error_plan9_test.go
error_posix_test.go
error_posix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
error_test.go os, net, internal/poll: return consistent error for closed socket 2017-04-26 00:03:14 +00:00
error_unix_test.go
error_windows_test.go
example_test.go net: update documentation on Listen and ListenPacket 2017-06-22 08:31:13 +00:00
external_test.go net: delay IP protocol stack-snooping system calls 2017-04-15 22:22:09 +00:00
fd_plan9.go net: delay IP protocol stack-snooping system calls 2017-04-15 22:22:09 +00:00
fd_unix.go net: calling File leaves the socket in nonblocking mode 2018-04-19 23:33:09 +00:00
fd_windows.go net: implement ReadMsg/WriteMsg on windows 2017-11-10 05:55:10 +00:00
file_plan9.go
file_stub.go
file_test.go os, net, internal/poll: return consistent error for closed socket 2017-04-26 00:03:14 +00:00
file_unix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
file_windows.go
file.go
hook_plan9.go
hook_unix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
hook_windows.go net: use WSASocket instead of socket call 2017-11-07 22:04:15 +00:00
hook.go
hosts_test.go all: change github.com issue links to golang.org 2017-11-04 04:13:41 +00:00
hosts.go
interface_bsd_test.go
interface_bsd.go
interface_bsdvar.go
interface_darwin.go
interface_freebsd.go
interface_linux_test.go
interface_linux.go net: remove unused Interface parameter 2017-03-07 16:37:07 +00:00
interface_plan9.go
interface_solaris.go
interface_stub.go
interface_test.go net: adjust the test for IPv4 loopback address block 2018-02-20 08:27:20 +00:00
interface_unix_test.go
interface_windows.go all: drop support for Windows Vista or below (Windows XP) 2018-02-15 17:24:42 +00:00
interface.go net: make zone helpers into methods of ipv6ZoneCache 2017-04-28 00:03:17 +00:00
ip_test.go net: optimize IP.String for IPv4 2018-03-09 17:03:05 +00:00
ip.go net: avoid unnecessary type conversions 2018-03-10 20:59:45 +00:00
iprawsock_plan9.go
iprawsock_posix.go net: make zone helpers into methods of ipv6ZoneCache 2017-04-28 00:03:17 +00:00
iprawsock_test.go net: validate network in Dial{,IP} and Listen{Packet,IP} for IP networks 2017-04-14 08:44:45 +00:00
iprawsock.go net: implement ReadMsg/WriteMsg on windows 2017-11-10 05:55:10 +00:00
ipsock_plan9.go net: defer file.close() + minor style cleanup 2017-04-26 03:12:20 +00:00
ipsock_posix.go net: set CLOEXEC on sockets used for capability probes 2018-01-03 22:46:08 +00:00
ipsock_test.go net: delay IP protocol stack-snooping system calls 2017-04-15 22:22:09 +00:00
ipsock.go net: don't return IPv4 unspecified addr for Resolve*Addr of [::] or [::]:n 2017-07-06 05:39:42 +00:00
listen_test.go net: fix data race in TestClosingListener 2017-10-13 15:19:59 +00:00
lookup_nacl.go
lookup_plan9.go net: fix LookupCNAME on Plan 9 2017-08-08 08:00:09 +00:00
lookup_test.go net: use retry in TestLookupGmailNS 2018-04-14 13:55:29 +00:00
lookup_unix.go net: treat a nil *Resolver as a zero one, as documented 2018-03-19 17:01:23 +00:00
lookup_windows_test.go net: make LookupCNAME's native behavior match its cgo behavior 2016-12-20 17:38:29 +00:00
lookup_windows.go net: treat a nil *Resolver as a zero one, as documented 2018-03-19 17:01:23 +00:00
lookup.go net: treat a nil *Resolver as a zero one, as documented 2018-03-19 17:01:23 +00:00
mac_test.go
mac.go
main_cloexec_test.go net, internal/poll, net/internal/socktest: use SOCK_{CLOEXEC,NONBLOCK} accept4/socket flags on OpenBSD 2018-02-26 16:59:38 +00:00
main_conf_test.go
main_noconf_test.go
main_plan9_test.go
main_posix_test.go
main_test.go net: don't return IPv4 unspecified addr for Resolve*Addr of [::] or [::]:n 2017-07-06 05:39:42 +00:00
main_unix_test.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
main_windows_test.go net: use WSASocket instead of socket call 2017-11-07 22:04:15 +00:00
mockserver_test.go net: delay IP protocol stack-snooping system calls 2017-04-15 22:22:09 +00:00
net_test.go os, net, internal/poll: return consistent error for closed socket 2017-04-26 00:03:14 +00:00
net_windows_test.go all: drop support for Windows Vista or below (Windows XP) 2018-02-15 17:24:42 +00:00
net.go net: calling File leaves the socket in nonblocking mode 2018-04-19 23:33:09 +00:00
netgo_unix_test.go net: avoid race on test hooks with DNS goroutines 2017-12-08 05:12:13 +00:00
nss_test.go
nss.go
packetconn_test.go
parse_test.go
parse.go net: accept 64 kB lines in /etc/hosts 2017-11-28 04:46:22 +00:00
pipe_test.go net: return io.ErrClosedPipe when possible from net.Pipe 2017-12-05 18:44:28 +00:00
pipe.go net: return io.ErrClosedPipe when possible from net.Pipe 2017-12-05 18:44:28 +00:00
platform_test.go net: skip unixpacket tests on netbsd/386 2017-11-29 19:24:24 +00:00
port_test.go
port_unix.go net: defer file.close() + minor style cleanup 2017-04-26 03:12:20 +00:00
port.go net: fix typo in parsePort documentation 2017-11-21 17:31:56 +00:00
protoconn_test.go all: drop support for Windows Vista or below (Windows XP) 2018-02-15 17:24:42 +00:00
rawconn_stub_test.go net: improve test coverage for syscall.RawConn 2018-03-31 23:41:59 +00:00
rawconn_test.go net: add missing deadline test for RawConn 2018-04-16 20:49:41 +00:00
rawconn_unix_test.go net: improve test coverage for syscall.RawConn 2018-03-31 23:41:59 +00:00
rawconn_windows_test.go net: implement (*syscall.RawConn).Read/Write on Windows 2018-04-14 05:36:36 +00:00
rawconn.go net: document caveats for (*syscall.RawConn).Write on Windows 2018-04-21 00:48:00 +00:00
sendfile_linux.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
sendfile_stub.go
sendfile_test.go
sendfile_unix_alt.go net: use same sendFile for freebsd/dragonfly and solaris 2018-04-06 14:48:05 +00:00
sendfile_windows.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
server_test.go
sock_bsd.go net: fix the kernel state name for TCP listen queue on FreeBSD 2018-02-02 00:04:20 +00:00
sock_cloexec.go net, internal/poll, net/internal/socktest: use SOCK_{CLOEXEC,NONBLOCK} accept4/socket flags on OpenBSD 2018-02-26 16:59:38 +00:00
sock_linux.go
sock_plan9.go
sock_posix.go net: handle spurious netpoll wakeups in connect 2017-06-15 22:39:39 +00:00
sock_stub.go
sock_windows.go net: use WSASocket instead of socket call 2017-11-07 22:04:15 +00:00
sockopt_bsd.go net: delay IP protocol stack-snooping system calls 2017-04-15 22:22:09 +00:00
sockopt_linux.go
sockopt_plan9.go
sockopt_posix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
sockopt_solaris.go
sockopt_stub.go
sockopt_windows.go
sockoptip_bsdvar.go net, internal/poll: enable ListenMulticastUDP on solaris 2017-08-09 23:52:12 +00:00
sockoptip_linux.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
sockoptip_posix.go net, internal/poll: enable ListenMulticastUDP on solaris 2017-08-09 23:52:12 +00:00
sockoptip_stub.go net, internal/poll: enable ListenMulticastUDP on solaris 2017-08-09 23:52:12 +00:00
sockoptip_windows.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
splice_linux.go net: add support for splice(2) in (*TCPConn).ReadFrom on Linux 2018-04-24 14:14:56 +00:00
splice_stub.go net: add support for splice(2) in (*TCPConn).ReadFrom on Linux 2018-04-24 14:14:56 +00:00
splice_test.go net: add support for splice(2) in (*TCPConn).ReadFrom on Linux 2018-04-24 14:14:56 +00:00
sys_cloexec.go net, internal/poll, net/internal/socktest: use SOCK_{CLOEXEC,NONBLOCK} accept4/socket flags on OpenBSD 2018-02-26 16:59:38 +00:00
tcpsock_plan9.go net: fix close on closed listener on Plan 9 2017-04-26 15:04:43 +00:00
tcpsock_posix.go net: add support for splice(2) in (*TCPConn).ReadFrom on Linux 2018-04-24 14:14:56 +00:00
tcpsock_test.go internal/poll: do not use Windows TransmitFile with pipes 2017-11-26 01:41:33 +00:00
tcpsock_unix_test.go net: don't let cancelation of a DNS lookup affect another lookup 2018-03-16 13:39:38 +00:00
tcpsock.go net: calling File leaves the socket in nonblocking mode 2018-04-19 23:33:09 +00:00
tcpsockopt_darwin.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
tcpsockopt_dragonfly.go net: use internal/poll for DragonFly setKeepAlivePeriod 2017-02-13 19:25:12 +00:00
tcpsockopt_openbsd.go
tcpsockopt_plan9.go
tcpsockopt_posix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
tcpsockopt_solaris.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
tcpsockopt_stub.go
tcpsockopt_unix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
tcpsockopt_windows.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
timeout_test.go net: fix UDPConn readers to return truncated payload size instead of 0 2018-02-21 10:40:03 +00:00
udpsock_plan9_test.go
udpsock_plan9.go
udpsock_posix.go net: make zone helpers into methods of ipv6ZoneCache 2017-04-28 00:03:17 +00:00
udpsock_test.go net: fix UDPConn readers to return truncated payload size instead of 0 2018-02-21 10:40:03 +00:00
udpsock.go net: implement ReadMsg/WriteMsg on windows 2017-11-10 05:55:10 +00:00
unixsock_linux_test.go net: move some Linux-specific tests to unixsock_linux_test.go file 2017-09-28 03:00:34 +00:00
unixsock_plan9.go
unixsock_posix.go
unixsock_test.go net: move some Linux-specific tests to unixsock_linux_test.go file 2017-09-28 03:00:34 +00:00
unixsock.go net: calling File leaves the socket in nonblocking mode 2018-04-19 23:33:09 +00:00
write_unix_test.go runtime: for kqueue treat EVFILT_READ with EV_EOF as permitting a write 2017-10-20 22:26:30 +00:00
writev_test.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00
writev_unix.go net: refactor poller into new internal/poll package 2017-02-13 18:36:28 +00:00