From 9a5b9253c4bce73a68b08e9f6bd6ac205d8ebc8f Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Fri, 13 Jan 2017 12:33:06 +0100 Subject: [PATCH] LoadBlob: use buffer as scratch space benchmark old bytes new bytes delta BenchmarkLoadBlob-4 1010128 2256 -99.78% --- src/restic/repository/repository.go | 28 +++++++++--------------- src/restic/repository/repository_test.go | 3 ++- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/restic/repository/repository.go b/src/restic/repository/repository.go index 809afb187..cb1e3ad69 100644 --- a/src/restic/repository/repository.go +++ b/src/restic/repository/repository.go @@ -81,17 +81,6 @@ func (r *Repository) LoadAndDecrypt(t restic.FileType, id restic.ID) ([]byte, er func (r *Repository) loadBlob(id restic.ID, t restic.BlobType, plaintextBuf []byte) (int, error) { debug.Log("load %v with id %v (buf %p, len %d)", t, id.Str(), plaintextBuf, len(plaintextBuf)) - // lookup plaintext size of blob - size, err := r.idx.LookupSize(id, t) - if err != nil { - return 0, err - } - - // make sure the plaintext buffer is large enough, extend otherwise - if len(plaintextBuf) < int(size) { - return 0, errors.Errorf("buffer is too small: %d < %d", len(plaintextBuf), size) - } - // lookup packs blobs, err := r.idx.Lookup(id, t) if err != nil { @@ -109,8 +98,8 @@ func (r *Repository) loadBlob(id restic.ID, t restic.BlobType, plaintextBuf []by // load blob from pack h := restic.Handle{Type: restic.DataFile, Name: blob.PackID.String()} - ciphertextBuf := make([]byte, blob.Length) - n, err := r.be.Load(h, ciphertextBuf, int64(blob.Offset)) + plaintextBuf = plaintextBuf[:cap(plaintextBuf)] + n, err := r.be.Load(h, plaintextBuf, int64(blob.Offset)) if err != nil { debug.Log("error loading blob %v: %v", blob, err) lastError = err @@ -125,7 +114,7 @@ func (r *Repository) loadBlob(id restic.ID, t restic.BlobType, plaintextBuf []by } // decrypt - n, err = r.decryptTo(plaintextBuf, ciphertextBuf) + n, err = r.decryptTo(plaintextBuf, plaintextBuf) if err != nil { lastError = errors.Errorf("decrypting blob %v failed: %v", id, err) continue @@ -528,7 +517,9 @@ func (r *Repository) Close() error { return r.be.Close() } -// LoadBlob loads a blob of type t from the repository to the buffer. +// LoadBlob loads a blob of type t from the repository to the buffer. buf must +// be large enough to hold the encrypted blob, since it is used as scratch +// space. func (r *Repository) LoadBlob(t restic.BlobType, id restic.ID, buf []byte) (int, error) { debug.Log("load blob %v into buf %p", id.Str(), buf) size, err := r.idx.LookupSize(id, t) @@ -536,8 +527,9 @@ func (r *Repository) LoadBlob(t restic.BlobType, id restic.ID, buf []byte) (int, return 0, err } - if len(buf) < int(size) { - return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), size) + buf = buf[:cap(buf)] + if len(buf) < int(size)+crypto.Extension { + return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), size+crypto.Extension) } n, err := r.loadBlob(id, t, buf) @@ -571,7 +563,7 @@ func (r *Repository) LoadTree(id restic.ID) (*restic.Tree, error) { } debug.Log("size is %d, create buffer", size) - buf := make([]byte, size) + buf := make([]byte, size+crypto.Extension) n, err := r.loadBlob(id, restic.TreeBlob, buf) if err != nil { diff --git a/src/restic/repository/repository_test.go b/src/restic/repository/repository_test.go index 34e642abb..978537d7f 100644 --- a/src/restic/repository/repository_test.go +++ b/src/restic/repository/repository_test.go @@ -11,6 +11,7 @@ import ( "restic" "restic/archiver" + "restic/crypto" "restic/repository" . "restic/test" ) @@ -152,7 +153,7 @@ func BenchmarkLoadBlob(b *testing.B) { defer cleanup() length := 1000000 - buf := make([]byte, length) + buf := make([]byte, length, length+crypto.Extension) _, err := io.ReadFull(rnd, buf) OK(b, err)