Giter Site home page Giter Site logo

zerocopy's Introduction

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.

zerocopy's People

Contributors

acln0 avatar n0madic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zerocopy's Issues

Windows support?

There are TransmitFile and TransmitPackets in Windows. Is it possible to implement zerocopy in windows?
I'm a rookie, just came to ask if this idea is possible after feeling the speed of zerocopy

support copy_file_range(2)

Besides splice(2) and tee(2), Linux also offers copy_file_range(2), opening the door for potential file-to-file copying optimizations, at the file system level. Perhaps we should look into supporting this. It doesn't look very difficult, at first sight.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.