Merge pull request #7108 from unclejack/archive_speedup
speed up archive Upstream-commit: 6b65e8817c76517b42264413e1aad4657fc3c1e0 Component: engine
This commit is contained in:
@@ -131,7 +131,7 @@ func (compression *Compression) Extension() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func addTarFile(path, name string, tw *tar.Writer) error {
|
||||
func addTarFile(path, name string, tw *tar.Writer, twBuf *bufio.Writer) error {
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -181,11 +181,18 @@ func addTarFile(path, name string, tw *tar.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(tw, file); err != nil {
|
||||
file.Close()
|
||||
|
||||
twBuf.Reset(tw)
|
||||
_, err = io.Copy(twBuf, file)
|
||||
file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
err = twBuf.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
twBuf.Reset(nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -328,6 +335,8 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
||||
options.Includes = []string{"."}
|
||||
}
|
||||
|
||||
twBuf := bufio.NewWriterSize(nil, twBufSize)
|
||||
|
||||
for _, include := range options.Includes {
|
||||
filepath.Walk(filepath.Join(srcPath, include), func(filePath string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
@@ -355,7 +364,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
||||
}
|
||||
}
|
||||
|
||||
if err := addTarFile(filePath, relFilePath, tw); err != nil {
|
||||
if err := addTarFile(filePath, relFilePath, tw, twBuf); err != nil {
|
||||
utils.Debugf("Can't add file %s to tar: %s\n", srcPath, err)
|
||||
}
|
||||
return nil
|
||||
@@ -394,6 +403,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
|
||||
defer decompressedArchive.Close()
|
||||
|
||||
tr := tar.NewReader(decompressedArchive)
|
||||
trBuf := bufio.NewReaderSize(nil, trBufSize)
|
||||
|
||||
var dirs []*tar.Header
|
||||
|
||||
@@ -439,7 +449,8 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := createTarFile(path, dest, hdr, tr, options == nil || !options.NoLchown); err != nil {
|
||||
trBuf.Reset(tr)
|
||||
if err := createTarFile(path, dest, hdr, trBuf, options == nil || !options.NoLchown); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -199,3 +199,42 @@ func TestUntarUstarGnuConflict(t *testing.T) {
|
||||
t.Fatalf("%s not found in the archive", "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm")
|
||||
}
|
||||
}
|
||||
|
||||
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string) (int, error) {
|
||||
fileData := []byte("fooo")
|
||||
for n := 0; n < numberOfFiles; n++ {
|
||||
fileName := fmt.Sprintf("file-%d", n)
|
||||
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
totalSize := numberOfFiles * len(fileData)
|
||||
return totalSize, nil
|
||||
}
|
||||
|
||||
func BenchmarkTarUntar(b *testing.B) {
|
||||
origin, err := ioutil.TempDir("", "docker-test-untar-origin")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
tempDir, err := ioutil.TempDir("", "docker-test-untar-destination")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
target := path.Join(tempDir, "dest")
|
||||
n, err := prepareUntarSourceDirectory(100, origin)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
b.SetBytes(int64(n))
|
||||
defer os.RemoveAll(origin)
|
||||
defer os.RemoveAll(tempDir)
|
||||
for n := 0; n < b.N; n++ {
|
||||
err := TarUntar(origin, target)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
os.RemoveAll(target)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -343,6 +344,7 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
|
||||
tw := tar.NewWriter(writer)
|
||||
|
||||
go func() {
|
||||
twBuf := bufio.NewWriterSize(nil, twBufSize)
|
||||
// In general we log errors here but ignore them because
|
||||
// during e.g. a diff operation the container can continue
|
||||
// mutating the filesystem and we can see transient errors
|
||||
@@ -365,7 +367,7 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
|
||||
}
|
||||
} else {
|
||||
path := filepath.Join(dir, change.Path)
|
||||
if err := addTarFile(path, change.Path[1:], tw); err != nil {
|
||||
if err := addTarFile(path, change.Path[1:], tw, twBuf); err != nil {
|
||||
utils.Debugf("Can't add file %s to tar: %s\n", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package archive
|
||||
|
||||
const twBufSize = 32 * 1024
|
||||
const trBufSize = 32 * 1024
|
||||
@@ -1,6 +1,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -32,6 +33,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
|
||||
}
|
||||
|
||||
tr := tar.NewReader(layer)
|
||||
trBuf := bufio.NewReaderSize(nil, trBufSize)
|
||||
|
||||
var dirs []*tar.Header
|
||||
|
||||
@@ -108,7 +110,8 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
|
||||
}
|
||||
}
|
||||
|
||||
srcData := io.Reader(tr)
|
||||
trBuf.Reset(tr)
|
||||
srcData := io.Reader(trBuf)
|
||||
srcHdr := hdr
|
||||
|
||||
// Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
|
||||
|
||||
Reference in New Issue
Block a user