mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 03:47:18 +00:00
io: provide generic-based WriteArray
goos: linux goarch: amd64 pkg: github.com/nspcc-dev/neo-go/pkg/io cpu: AMD Ryzen 7 PRO 7840U w/ Radeon 780M Graphics BenchmarkWriteArray/WriteArray_method,_value-16 2419993 506.1 ns/op 184 B/op 11 allocs/op BenchmarkWriteArray/WriteArray_method,_pointer-16 4159906 294.7 ns/op 24 B/op 1 allocs/op BenchmarkWriteArray/WriteArray_generic,_value-16 9217713 128.8 ns/op 0 B/op 0 allocs/op BenchmarkWriteArray/WriteArray_generic,_pointer-16 9575917 131.8 ns/op 0 B/op 0 allocs/op BenchmarkWriteArray/open-coded,_value-16 9100132 131.4 ns/op 0 B/op 0 allocs/op BenchmarkWriteArray/open-coded,_pointer-16 9153250 131.9 ns/op 0 B/op 0 allocs/op PASS ok github.com/nspcc-dev/neo-go/pkg/io 541.663s Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
parent
dc6c195637
commit
c953c6cece
2 changed files with 110 additions and 0 deletions
98
pkg/io/bench_test.go
Normal file
98
pkg/io/bench_test.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
package io
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type someval struct {
|
||||
a int
|
||||
b int
|
||||
}
|
||||
|
||||
func (s someval) EncodeBinary(w *BinWriter) {
|
||||
w.WriteU64LE(uint64(s.a))
|
||||
w.WriteU64LE(uint64(s.b))
|
||||
}
|
||||
|
||||
type somepoint struct {
|
||||
a int
|
||||
b int
|
||||
}
|
||||
|
||||
func (s *somepoint) EncodeBinary(w *BinWriter) {
|
||||
w.WriteU64LE(uint64(s.a))
|
||||
w.WriteU64LE(uint64(s.b))
|
||||
}
|
||||
|
||||
func BenchmarkWriteArray(b *testing.B) {
|
||||
const numElems = 10
|
||||
var (
|
||||
v = slices.Repeat([]someval{{}}, numElems)
|
||||
p = slices.Repeat([]*somepoint{{}}, numElems)
|
||||
)
|
||||
|
||||
w := NewBufBinWriter()
|
||||
w.Grow(numElems * 32) // more than needed, we don't need reallocations here.
|
||||
|
||||
b.Run("WriteArray method, value", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
w.WriteArray(v)
|
||||
}
|
||||
})
|
||||
b.Run("WriteArray method, pointer", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
w.WriteArray(p)
|
||||
}
|
||||
})
|
||||
b.Run("WriteArray generic, value", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
WriteArray(w.BinWriter, v)
|
||||
}
|
||||
})
|
||||
b.Run("WriteArray generic, pointer", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
WriteArray(w.BinWriter, p)
|
||||
}
|
||||
})
|
||||
b.Run("open-coded, value", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
w.WriteVarUint(uint64(len(v)))
|
||||
for i := range v {
|
||||
v[i].EncodeBinary(w.BinWriter)
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("open-coded, pointer", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
w.Reset()
|
||||
b.StartTimer()
|
||||
w.WriteVarUint(uint64(len(p)))
|
||||
for i := range v {
|
||||
p[i].EncodeBinary(w.BinWriter)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
|
@ -68,6 +68,9 @@ func (w *BinWriter) WriteBool(b bool) {
|
|||
// WriteArray writes a slice or an array arr into w. Note that nil slices and
|
||||
// empty slices are gonna be treated the same resulting in an equal zero-length
|
||||
// array encoded.
|
||||
//
|
||||
// Deprecated: Go doesn't support generic methods, but [WriteArray] function
|
||||
// is much faster that this method.
|
||||
func (w *BinWriter) WriteArray(arr any) {
|
||||
switch val := reflect.ValueOf(arr); val.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
@ -94,6 +97,15 @@ func (w *BinWriter) WriteArray(arr any) {
|
|||
}
|
||||
}
|
||||
|
||||
// WriteArray writes a slice arr into w. It is a generic-based version of
|
||||
// [BinWriter.WriteArray] which works much faster.
|
||||
func WriteArray[Slice ~[]E, E Serializable](w *BinWriter, arr Slice) {
|
||||
w.WriteVarUint(uint64(len(arr)))
|
||||
for i := range arr {
|
||||
arr[i].EncodeBinary(w)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteVarUint writes a uint64 into the underlying writer using variable-length encoding.
|
||||
func (w *BinWriter) WriteVarUint(val uint64) {
|
||||
if w.Err != nil {
|
||||
|
|
Loading…
Reference in a new issue