Просмотр исходного кода

Support decoding into pre-allocated buffers

Sean Hanson 7 лет назад
Родитель
Сommit
add554803d
2 измененных файлов с 83 добавлено и 3 удалено
  1. 16 3
      snappy.go
  2. 67 0
      snappy_test.go

+ 16 - 3
snappy.go

@@ -28,24 +28,37 @@ func Encode(src []byte) []byte {
 // Decode decodes snappy data whether it is traditional unframed
 // or includes the xerial framing format.
 func Decode(src []byte) ([]byte, error) {
+	return DecodeInto(nil, src)
+}
+
+// DecodeInto decodes snappy data whether it is traditional unframed
+// or includes the xerial framing format into the specified 'dst'.
+// It is assumed that the entirety of dst including all capacity is available
+// for use by this function. If dst is nil *or* insufficiently large to hold
+// the decoded chunks, new chunks will be allocated.
+func DecodeInto(dst, src []byte) ([]byte, error) {
 	var max = len(src)
 	if max < len(xerialHeader) {
 		return nil, ErrMalformed
 	}
 
 	if !bytes.Equal(src[:8], xerialHeader) {
-		return master.Decode(nil, src)
+		return master.Decode(dst[:cap(dst)], src)
 	}
 
 	if max < sizeOffset+sizeBytes {
 		return nil, ErrMalformed
 	}
 
+	if dst == nil {
+		dst = make([]byte, 0, len(src))
+	}
+
+	dst = dst[:0]
 	var (
 		pos   = sizeOffset
-		dst   = make([]byte, 0, len(src))
 		chunk []byte
-		err   error
+		err       error
 	)
 
 	for pos+sizeBytes <= max {

+ 67 - 0
snappy_test.go

@@ -93,3 +93,70 @@ func TestSnappyMasterDecodeFailed(t *testing.T) {
 		t.Errorf("unexpected err: %v", err)
 	}
 }
+
+
+func BenchmarkSnappyDecode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+
+	for n := 0; n < b.N; n++ {
+		for _, test := range snappyTestCases {
+			_, err := Decode(test)
+			if err != nil {
+				b.Error("Encoding error: ", err)
+			}
+		}
+	}
+}
+
+func BenchmarkSnappyStreamDecode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+
+	for n := 0; n < b.N; n++ {
+		for _, test := range snappyStreamTestCases {
+			_, err := Decode(test)
+			if err != nil {
+				b.Error("Encoding error: ", err)
+			}
+		}
+	}
+}
+
+func BenchmarkSnappyDecodeInto(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+
+	var (
+		dst []byte
+		err error
+	)
+
+	for n := 0; n < b.N; n++ {
+		for _, test := range snappyTestCases {
+			dst, err = DecodeInto(dst, test)
+			if err != nil {
+				b.Error("Encoding error: ", err)
+			}
+		}
+	}
+}
+
+func BenchmarkSnappyStreamDecodeInto(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+
+	var (
+		dst = make([]byte, 1024, 1024)
+		err error
+	)
+
+	for n := 0; n < b.N; n++ {
+		for _, test := range snappyStreamTestCases {
+			dst, err = DecodeInto(dst, test)
+			if err != nil {
+				b.Error("Encoding error: ", err)
+			}
+		}
+	}
+}