rlp: optimize byte array handling (#22924)

This change improves the performance of encoding/decoding [N]byte.

    name                     old time/op    new time/op    delta
    DecodeByteArrayStruct-8     336ns ± 0%     246ns ± 0%  -26.98%  (p=0.000 n=9+10)
    EncodeByteArrayStruct-8     225ns ± 1%     148ns ± 1%  -34.12%  (p=0.000 n=10+10)

    name                     old alloc/op   new alloc/op   delta
    DecodeByteArrayStruct-8      120B ± 0%       48B ± 0%  -60.00%  (p=0.000 n=10+10)
    EncodeByteArrayStruct-8     0.00B          0.00B          ~     (all equal)
This commit is contained in:
Felix Lange
2021-05-22 15:10:16 +02:00
committed by GitHub
parent 0d076d92db
commit 154ca32a8a
6 changed files with 146 additions and 50 deletions

View File

@ -26,6 +26,8 @@ import (
"reflect"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common/math"
)
func TestStreamKind(t *testing.T) {
@ -1063,7 +1065,7 @@ func ExampleStream() {
// [102 111 111 98 97 114] <nil>
}
func BenchmarkDecode(b *testing.B) {
func BenchmarkDecodeUints(b *testing.B) {
enc := encodeTestSlice(90000)
b.SetBytes(int64(len(enc)))
b.ReportAllocs()
@ -1078,7 +1080,7 @@ func BenchmarkDecode(b *testing.B) {
}
}
func BenchmarkDecodeIntSliceReuse(b *testing.B) {
func BenchmarkDecodeUintsReused(b *testing.B) {
enc := encodeTestSlice(100000)
b.SetBytes(int64(len(enc)))
b.ReportAllocs()
@ -1093,6 +1095,44 @@ func BenchmarkDecodeIntSliceReuse(b *testing.B) {
}
}
func BenchmarkDecodeByteArrayStruct(b *testing.B) {
enc, err := EncodeToBytes(&byteArrayStruct{})
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(enc)))
b.ReportAllocs()
b.ResetTimer()
var out byteArrayStruct
for i := 0; i < b.N; i++ {
if err := DecodeBytes(enc, &out); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkDecodeBigInts(b *testing.B) {
ints := make([]*big.Int, 200)
for i := range ints {
ints[i] = math.BigPow(2, int64(i))
}
enc, err := EncodeToBytes(ints)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(enc)))
b.ReportAllocs()
b.ResetTimer()
var out []*big.Int
for i := 0; i < b.N; i++ {
if err := DecodeBytes(enc, &out); err != nil {
b.Fatal(err)
}
}
}
func encodeTestSlice(n uint) []byte {
s := make([]uint, n)
for i := uint(0); i < n; i++ {