webdav: make memFile.Write allocate less often.
benchmark old ns/op new ns/op delta
BenchmarkMemFileWrite 8498028 625563 -92.64%
Change-Id: Iec7dd3931c891c9d6d9d5c6ccd05300b031a5f86
diff --git a/webdav/file_test.go b/webdav/file_test.go
index ff68c4a..d95d5a8 100644
--- a/webdav/file_test.go
+++ b/webdav/file_test.go
@@ -252,9 +252,12 @@
"write C",
"wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C",
"wantSize 41",
- "seek set 43 want 43",
"write D",
- "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C..D",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........CD",
+ "wantSize 42",
+ "seek set 43 want 43",
+ "write E",
+ "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........CD.E",
"wantSize 44",
"seek set 0 want 0",
"write 5*123456789_",
@@ -396,3 +399,54 @@
}
}
}
+
+// TestMemFileWriteAllocs tests that writing N consecutive 1KiB chunks to a
+// memFile doesn't allocate a new buffer for each of those N times. Otherwise,
+// calling io.Copy(aMemFile, src) is likely to have quadratic complexity.
+func TestMemFileWriteAllocs(t *testing.T) {
+ fs := NewMemFS()
+ f, err := fs.OpenFile("/xxx", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ t.Fatalf("OpenFile: %v", err)
+ }
+ defer f.Close()
+
+ xxx := make([]byte, 1024)
+ for i := range xxx {
+ xxx[i] = 'x'
+ }
+
+ a := testing.AllocsPerRun(100, func() {
+ f.Write(xxx)
+ })
+ // AllocsPerRun returns an integral value, so we compare the rounded-down
+ // number to zero.
+ if a > 0 {
+ t.Fatalf("%v allocs per run, want 0", a)
+ }
+}
+
+func BenchmarkMemFileWrite(b *testing.B) {
+ fs := NewMemFS()
+ xxx := make([]byte, 1024)
+ for i := range xxx {
+ xxx[i] = 'x'
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ f, err := fs.OpenFile("/xxx", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ b.Fatalf("OpenFile: %v", err)
+ }
+ for j := 0; j < 100; j++ {
+ f.Write(xxx)
+ }
+ if err := f.Close(); err != nil {
+ b.Fatalf("Close: %v", err)
+ }
+ if err := fs.RemoveAll("/xxx"); err != nil {
+ b.Fatalf("RemoveAll: %v", err)
+ }
+ }
+}