From 7714dcacbca1961543fbad0c8bc2a2afc7baaaee Mon Sep 17 00:00:00 2001 From: Martin Garton Date: Mon, 30 Sep 2019 09:27:38 +0000 Subject: encoding/binary: add float support to fast path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds float type support to the main switch blocks in Read and Write, instead of falling back to reflection. This gives a considerable speedup for the float types: ReadFloats-8 129ns ± 9% 70ns ± 8% -46.02% (p=0.001 n=7+7) WriteFloats-8 131ns ± 6% 86ns ±11% -34.59% (p=0.001 n=7+7) ReadSlice1000Float32s-8 14.6µs ±14% 4.8µs ±12% -67.29% (p=0.001 n=7+7) WriteSlice1000Float32s-8 16.4µs ±20% 4.7µs ± 8% -71.01% (p=0.001 n=7+7) Change-Id: I0be99d068b07d10dd6eb1137b45eff6f7c216b87 GitHub-Last-Rev: 4ff326e99ca35977d819f0ba29c10d9efc7e811c GitHub-Pull-Request: golang/go#31803 Reviewed-on: https://go-review.googlesource.com/c/go/+/174959 Reviewed-by: Brad Fitzpatrick --- src/encoding/binary/binary_test.go | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/encoding/binary/binary_test.go') diff --git a/src/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go index 778de6908c..aeb4212ec2 100644 --- a/src/encoding/binary/binary_test.go +++ b/src/encoding/binary/binary_test.go @@ -634,3 +634,75 @@ func BenchmarkLittleEndianPutUint64(b *testing.B) { LittleEndian.PutUint64(putbuf[:], uint64(i)) } } + +func BenchmarkReadFloats(b *testing.B) { + var ls Struct + bsr := &byteSliceReader{} + var r io.Reader = bsr + b.SetBytes(4 + 8) + b.ResetTimer() + for i := 0; i < b.N; i++ { + bsr.remain = big[30:] + Read(r, BigEndian, &ls.Float32) + Read(r, BigEndian, &ls.Float64) + } + b.StopTimer() + want := s + want.Int8 = 0 + want.Int16 = 0 + want.Int32 = 0 + want.Int64 = 0 + want.Uint8 = 0 + want.Uint16 = 0 + want.Uint32 = 0 + want.Uint64 = 0 + want.Complex64 = 0 + want.Complex128 = 0 + want.Array = [4]uint8{0, 0, 0, 0} + want.Bool = false + want.BoolArray = [4]bool{false, false, false, false} + if b.N > 0 && !reflect.DeepEqual(ls, want) { + b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) + } +} + +func BenchmarkWriteFloats(b *testing.B) { + buf := new(bytes.Buffer) + var w io.Writer = buf + b.SetBytes(4 + 8) + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + Write(w, BigEndian, s.Float32) + Write(w, BigEndian, s.Float64) + } + b.StopTimer() + if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) { + b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8]) + } +} + +func BenchmarkReadSlice1000Float32s(b *testing.B) { + bsr := &byteSliceReader{} + slice := make([]float32, 1000) + buf := make([]byte, len(slice)*4) + b.SetBytes(int64(len(buf))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + bsr.remain = buf + Read(bsr, BigEndian, slice) + } +} + +func BenchmarkWriteSlice1000Float32s(b *testing.B) { + slice := make([]float32, 1000) + buf := new(bytes.Buffer) + var w io.Writer = buf + b.SetBytes(4 * 1000) + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + Write(w, BigEndian, slice) + } + b.StopTimer() +} -- cgit v1.3