diff --git a/server.go b/server.go index eaa42d155..17839c554 100644 --- a/server.go +++ b/server.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "sync" "github.com/restic/restic/backend" "github.com/restic/restic/debug" @@ -277,6 +278,12 @@ func (s Server) SaveFrom(t backend.Type, id backend.ID, length uint, rd io.Reade return blob, nil } +var zWriterPool = sync.Pool{ + New: func() interface{} { + return zlib.NewWriter(nil) + }, +} + // SaveJSON serialises item as JSON and encrypts and saves it in the backend as // type t. func (s Server) SaveJSON(t backend.Type, item interface{}) (Blob, error) { @@ -286,7 +293,9 @@ func (s Server) SaveJSON(t backend.Type, item interface{}) (Blob, error) { } encWr := s.key.EncryptTo(backendBlob) - wr := zlib.NewWriter(encWr) + wr := zWriterPool.Get().(*zlib.Writer) + defer zWriterPool.Put(wr) + wr.Reset(encWr) if err != nil { return Blob{}, fmt.Errorf("zlib.NewWriter: %v", err) } diff --git a/server_test.go b/server_test.go new file mode 100644 index 000000000..9272fa24a --- /dev/null +++ b/server_test.go @@ -0,0 +1,68 @@ +package restic_test + +import ( + "bytes" + "crypto/sha256" + "encoding/json" + "testing" + + "github.com/restic/restic" + "github.com/restic/restic/backend" +) + +type testJSONStruct struct { + Foo uint32 + Bar string + Baz []byte +} + +var serverTests = []testJSONStruct{ + testJSONStruct{Foo: 23, Bar: "Teststring", Baz: []byte("xx")}, +} + +func TestSaveJSON(t *testing.T) { + be := setupBackend(t) + defer teardownBackend(t, be) + key := setupKey(t, be, "geheim") + server := restic.NewServerWithKey(be, key) + + for _, obj := range serverTests { + data, err := json.Marshal(obj) + ok(t, err) + data = append(data, '\n') + h := sha256.Sum256(data) + + blob, err := server.SaveJSON(backend.Tree, obj) + ok(t, err) + + assert(t, bytes.Equal(h[:], blob.ID), + "TestSaveJSON: wrong plaintext ID: expected %02x, got %02x", + h, blob.ID) + } +} + +func BenchmarkSaveJSON(t *testing.B) { + be := setupBackend(t) + defer teardownBackend(t, be) + key := setupKey(t, be, "geheim") + server := restic.NewServerWithKey(be, key) + + t.ResetTimer() + //t.SetBytes(int64(size)) + + obj := serverTests[0] + + data, err := json.Marshal(obj) + ok(t, err) + data = append(data, '\n') + h := sha256.Sum256(data) + + for i := 0; i < t.N; i++ { + blob, err := server.SaveJSON(backend.Tree, obj) + ok(t, err) + + assert(t, bytes.Equal(h[:], blob.ID), + "TestSaveJSON: wrong plaintext ID: expected %02x, got %02x", + h, blob.ID) + } +}