Skip to content

proposal: archive/tar: support zero-copy reading/writing #70807

@hanwen

Description

@hanwen

Proposal Details

the container ecosystem (podman,docker) spends its days creating and consuming huge .tar files. There is potential for significant speed-up here by having the tar package use zero-copy file transport.

The change is straightforward, but involves an API change, so opening a proposal.

with the following change, tarring up a 2G file from tmpfs to tmpfs goes from 2.0s to 1.3s

diff -u /home/hanwen/vc/go/src/archive/tar/writer.go hacktar/writer.go
--- /home/hanwen/vc/go/src/archive/tar/writer.go	2024-08-22 14:56:29.586690369 +0200
+++ hacktar/writer.go	2024-12-12 15:01:22.150045055 +0100
@@ -9,6 +9,7 @@
 	"fmt"
 	"io"
 	"io/fs"
+	"log"
 	"path"
 	"slices"
 	"strings"
@@ -491,7 +492,7 @@
 //
 // TODO(dsnet): Re-export this when adding sparse file support.
 // See https://golang.org/issue/22735
-func (tw *Writer) readFrom(r io.Reader) (int64, error) {
+func (tw *Writer) ReadFrom(r io.Reader) (int64, error) {
 	if tw.err != nil {
 		return 0, tw.err
 	}
@@ -550,6 +551,16 @@
 }
 
 func (fw *regFileWriter) ReadFrom(r io.Reader) (int64, error) {
+	log.Println("hanwen")
+	if _, ok := fw.w.(io.ReaderFrom); ok {
+		n, err := io.Copy(fw.w, r)
+		if n > fw.nb {
+			return n, fmt.Errorf("read %d bytes, beyond max %d", n, fw.nb)
+		}
+		fw.nb -= n
+		return n, err
+	}
+
 	return io.Copy(struct{ io.Writer }{fw}, r)
 }
 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions