Merge pull request #7108 from unclejack/archive_speedup

speed up archive
Upstream-commit: 6b65e8817c76517b42264413e1aad4657fc3c1e0
Component: engine
This commit is contained in:
Victor Vieux
2014-07-23 16:54:35 -07:00
5 changed files with 67 additions and 8 deletions
+17 -6
View File
@@ -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
}
+39
View File
@@ -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)
}
}
+3 -1
View File
@@ -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)
}
}
+4
View File
@@ -0,0 +1,4 @@
package archive
const twBufSize = 32 * 1024
const trBufSize = 32 * 1024
+4 -1
View File
@@ -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