zerocopy

Zero-copy I/O primitives and pipelines for Go. Linux-specific.

Github星跟踪图

zerocopy

import "acln.ro/zerocopy"

GoDoc

Package zerocopy facilitates the construction of accelerated I/O
pipelines. Under circumstances where I/O acceleration is not
possible, the pipelines fall back to userspace data transfer
transparently. Currently, package zerocopy only offers accelerated
I/O on Linux, and for specific types of file descriptors.

Status

This package is alpha quality software. It is under active development,
it almost certainly has bugs, or exhibits deadlocks.

Bug reports and contributions are welcome.

Requirements

Package zerocopy requires at least Go 1.12. On the Go side of
things, package zerocopy uses type assertions on the io.Reader
and io.Writer arguments to ReadFrom, WriteTo, or Transfer,
in order to determine splice capabilities.

The first requirement is for the Go types to implement
the syscall.Conn
interface. Secondly, the syscall.Conn implementations must be
backed by real file descriptors, the file descriptors must be
set to non-blocking mode, and must be registered with the runtime
network poller.

More concretely, *net.TCPConn and *net.UnixConn (on the "unix"
network, with SOCK_STREAM semantics) should work out of the
box. Non-exotic varieties of *os.File should also work.

Generally, file descriptors involved in such transfers must be
stream-oriented. Stream-orientation is a necessary, but not sufficient
condition for splice(2) to work on a file descriptor. Consult the
appropriate subsystem manual, or the kernel source code, if you need
to be sure.

Usage

Consider this diagram of a proxy server:

+----------+       +----------------+       +------------+, +<------+                +<------+, upstream, P, proxy server, Q, downstream, +------->                +------->, +----------+       +----------------+       +------------+

P and Q represent streaming communication protocols, for example
TCP, or a streaming UNIX domain socket. Implementing this proxy server
is straightforward:

func proxy(upstream, downstream net.Conn) error {
	go zerocopy.Transfer(upstream, downstream)
	go zerocopy.Transfer(downstream, upstream)

	// ... wait, clean up, etc.
}

Consider now a slightly more complex data flow diagram.

                     +-----------+, recording, +-----+-----+
                           ^, file, +----------+       +-------+--------+       +----------+, TCP, TCP, camera  +------>+     server     +------>+  client, +----------+       +----------------+       +----------+

This server component could be implemented as follows:

func server(camera net.Conn, recording *os.File, client net.Conn) error {
	// Create a pipe between the camera and the client.
	campipe, err := zerocopy.NewPipe()
	if err != nil {
		return err
	}
	defer campipe.Close()

	// Create a pipe to the recording.
	recpipe, err := zerocopy.NewPipe()
	if err != nil {
		return err
	}
	defer recpipe.Close()

	// Arrange for data on campipe to be duplicated to recpipe.
	campipe.Tee(recpipe)

	// Run the world.
	go campipe.ReadFrom(camera)
	go recpipe.WriteTo(recording)
	go campipe.WriteTo(client)

	// ... wait, clean up etc.
}

Additional reading

Benchmarks

Transfer - in userspace vs. splice-accelerated

benchmark                                    old ns/op     new ns/op     delta
BenchmarkTransfer/tcp-to-tcp/1024-4          3972          3667          -7.68%
BenchmarkTransfer/tcp-to-tcp/2048-4          3361          3193          -5.00%
BenchmarkTransfer/tcp-to-tcp/4096-4          3522          3613          +2.58%
BenchmarkTransfer/tcp-to-tcp/8192-4          4400          3840          -12.73%
BenchmarkTransfer/tcp-to-tcp/16384-4         6293          4038          -35.83%
BenchmarkTransfer/tcp-to-tcp/32768-4         13637         5465          -59.93%
BenchmarkTransfer/tcp-to-tcp/65536-4         22652         10155         -55.17%
BenchmarkTransfer/tcp-to-tcp/131072-4        44927         17892         -60.18%
BenchmarkTransfer/tcp-to-tcp/262144-4        111338        37230         -66.56%
BenchmarkTransfer/tcp-to-tcp/524288-4        227587        77118         -66.11%
BenchmarkTransfer/tcp-to-tcp/1048576-4       482285        295034        -38.83%
BenchmarkTransfer/unix-to-tcp/1024-4         1173          1342          +14.41%
BenchmarkTransfer/unix-to-tcp/2048-4         1376          1478          +7.41%
BenchmarkTransfer/unix-to-tcp/4096-4         2337          1814          -22.38%
BenchmarkTransfer/unix-to-tcp/8192-4         2879          2167          -24.73%
BenchmarkTransfer/unix-to-tcp/16384-4        5353          3422          -36.07%
BenchmarkTransfer/unix-to-tcp/32768-4        9816          5651          -42.43%
BenchmarkTransfer/unix-to-tcp/65536-4        20921         11871         -43.26%
BenchmarkTransfer/unix-to-tcp/131072-4       37644         21996         -41.57%
BenchmarkTransfer/unix-to-tcp/262144-4       76739         44324         -42.24%
BenchmarkTransfer/unix-to-tcp/524288-4       148243        78678         -46.93%
BenchmarkTransfer/unix-to-tcp/1048576-4      311495        151634        -51.32%
BenchmarkTransfer/tcp-to-unix/1024-4         4258          3993          -6.22%
BenchmarkTransfer/tcp-to-unix/2048-4         3268          3299          +0.95%
BenchmarkTransfer/tcp-to-unix/4096-4         3572          3253          -8.93%
BenchmarkTransfer/tcp-to-unix/8192-4         2776          3737          +34.62%
BenchmarkTransfer/tcp-to-unix/16384-4        4556          4989          +9.50%
BenchmarkTransfer/tcp-to-unix/32768-4        10038         6707          -33.18%
BenchmarkTransfer/tcp-to-unix/65536-4        19597         10823         -44.77%
BenchmarkTransfer/tcp-to-unix/131072-4       40673         15997         -60.67%
BenchmarkTransfer/tcp-to-unix/262144-4       76247         30427         -60.09%
BenchmarkTransfer/tcp-to-unix/524288-4       148763        60432         -59.38%
BenchmarkTransfer/tcp-to-unix/1048576-4      307637        117157        -61.92%
BenchmarkTransfer/unix-to-unix/1024-4        1090          1102          +1.10%
BenchmarkTransfer/unix-to-unix/2048-4        1094          1111          +1.55%
BenchmarkTransfer/unix-to-unix/4096-4        1558          1591          +2.12%
BenchmarkTransfer/unix-to-unix/8192-4        2013          2597          +29.01%
BenchmarkTransfer/unix-to-unix/16384-4       3373          2765          -18.03%
BenchmarkTransfer/unix-to-unix/32768-4       6864          3327          -51.53%
BenchmarkTransfer/unix-to-unix/65536-4       14177         9587          -32.38%
BenchmarkTransfer/unix-to-unix/131072-4      26012         17204         -33.86%
BenchmarkTransfer/unix-to-unix/262144-4      48500         31884         -34.26%
BenchmarkTransfer/unix-to-unix/524288-4      102363        62569         -38.88%
BenchmarkTransfer/unix-to-unix/1048576-4     204508        131515        -35.69%

benchmark                                    old MB/s     new MB/s     speedup
BenchmarkTransfer/tcp-to-tcp/1024-4          257.77       279.21       1.08x
BenchmarkTransfer/tcp-to-tcp/2048-4          609.32       641.23       1.05x
BenchmarkTransfer/tcp-to-tcp/4096-4          1162.72      1133.52      0.97x
BenchmarkTransfer/tcp-to-tcp/8192-4          1861.72      2132.81      1.15x
BenchmarkTransfer/tcp-to-tcp/16384-4         2603.52      4057.02      1.56x
BenchmarkTransfer/tcp-to-tcp/32768-4         2402.79      5995.63      2.50x
BenchmarkTransfer/tcp-to-tcp/65536-4         2893.13      6453.09      2.23x
BenchmarkTransfer/tcp-to-tcp/131072-4        2917.40      7325.41      2.51x
BenchmarkTransfer/tcp-to-tcp/262144-4        2354.48      7041.18      2.99x
BenchmarkTransfer/tcp-to-tcp/524288-4        2303.68      6798.46      2.95x
BenchmarkTransfer/tcp-to-tcp/1048576-4       2174.18      3554.08      1.63x
BenchmarkTransfer/unix-to-tcp/1024-4         872.62       762.84       0.87x
BenchmarkTransfer/unix-to-tcp/2048-4         1487.48      1385.61      0.93x
BenchmarkTransfer/unix-to-tcp/4096-4         1752.30      2257.64      1.29x
BenchmarkTransfer/unix-to-tcp/8192-4         2844.91      3780.21      1.33x
BenchmarkTransfer/unix-to-tcp/16384-4        3060.64      4787.20      1.56x
BenchmarkTransfer/unix-to-tcp/32768-4        3337.99      5797.91      1.74x
BenchmarkTransfer/unix-to-tcp/65536-4        3132.48      5520.36      1.76x
BenchmarkTransfer/unix-to-tcp/131072-4       3481.81      5958.82      1.71x
BenchmarkTransfer/unix-to-tcp/262144-4       3416.03      5914.26      1.73x
BenchmarkTransfer/unix-to-tcp/524288-4       3536.66      6663.65      1.88x
BenchmarkTransfer/unix-to-tcp/1048576-4      3366.26      6915.13      2.05x
BenchmarkTransfer/tcp-to-unix/1024-4         240.46       256.40       1.07x
BenchmarkTransfer/tcp-to-unix/2048-4         626.59       620.76       0.99x
BenchmarkTransfer/tcp-to-unix/4096-4         1146.67      1258.78      1.10x
BenchmarkTransfer/tcp-to-unix/8192-4         2950.44      2191.74      0.74x
BenchmarkTransfer/tcp-to-unix/16384-4        3596.05      3283.65      0.91x
BenchmarkTransfer/tcp-to-unix/32768-4        3264.14      4884.94      1.50x
BenchmarkTransfer/tcp-to-unix/65536-4        3344.10      6055.24      1.81x
BenchmarkTransfer/tcp-to-unix/131072-4       3222.57      8193.26      2.54x
BenchmarkTransfer/tcp-to-unix/262144-4       3438.06      8615.32      2.51x
BenchmarkTransfer/tcp-to-unix/524288-4       3524.30      8675.60      2.46x
BenchmarkTransfer/tcp-to-unix/1048576-4      3408.48      8950.12      2.63x
BenchmarkTransfer/unix-to-unix/1024-4        939.04       929.05       0.99x
BenchmarkTransfer/unix-to-unix/2048-4        1871.53      1842.52      0.98x
BenchmarkTransfer/unix-to-unix/4096-4        2627.44      2574.18      0.98x
BenchmarkTransfer/unix-to-unix/8192-4        4068.58      3153.97      0.78x
BenchmarkTransfer/unix-to-unix/16384-4       4856.35      5925.29      1.22x
BenchmarkTransfer/unix-to-unix/32768-4       4773.31      9846.81      2.06x
BenchmarkTransfer/unix-to-unix/65536-4       4622.41      6835.42      1.48x
BenchmarkTransfer/unix-to-unix/131072-4      5038.74      7618.43      1.51x
BenchmarkTransfer/unix-to-unix/262144-4      5405.02      8221.65      1.52x
BenchmarkTransfer/unix-to-unix/524288-4      5121.83      8379.33      1.64x
BenchmarkTransfer/unix-to-unix/1048576-4     5127.30      7972.99      1.56x

Tee

TODO(acln): add a benchmark

License

Pacakge zerocopy is distributed under a BSD-style license. Apart from
the work belonging to the author, package zerocopy adapts and copies
Go standard library code and tests. See the LICENSE file, as well as
the individual copyright headers in source files.

主要指标

概览
名称与所有者acln0/zerocopy
主编程语言Go
编程语言Go (语言数: 1)
平台
许可证BSD 3-Clause "New" or "Revised" License
所有者活动
创建于2019-03-29 00:28:22
推送于2024-08-03 13:23:00
最后一次提交2019-04-10 15:23:15
发布数0
用户参与
星数546
关注者数9
派生数35
提交数26
已启用问题?
问题数3
打开的问题数3
拉请求数1
打开的拉请求数1
关闭的拉请求数1
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?