*: do not use WriteArray
for frequently used items
`WriteArray` involves reflection, it makes sense to optimize serialization of transactions and application logs which are serialized constantly. Adding case in a type switch in `WriteArray` is not an option because we don't want new dependencies for `io` package. ``` name old time/op new time/op delta AppExecResult_EncodeBinary-8 852ns ± 3% 656ns ± 2% -22.94% (p=0.000 n=10+9) name old alloc/op new alloc/op delta AppExecResult_EncodeBinary-8 448B ± 0% 376B ± 0% -16.07% (p=0.000 n=10+10) name old allocs/op new allocs/op delta AppExecResult_EncodeBinary-8 7.00 ± 0% 5.00 ± 0% -28.57% (p=0.000 n=10+10) ``` ``` name old time/op new time/op delta Transaction_Bytes-8 1.29µs ± 3% 0.76µs ± 5% -41.52% (p=0.000 n=9+10) name old alloc/op new alloc/op delta Transaction_Bytes-8 1.21kB ± 0% 1.01kB ± 0% -16.56% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Transaction_Bytes-8 12.0 ± 0% 7.0 ± 0% -41.67% (p=0.000 n=10+10) ``` Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
43ee671f36
commit
291a29af1e
4 changed files with 52 additions and 4 deletions
|
@ -61,7 +61,10 @@ func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) {
|
|||
for _, it := range aer.Stack {
|
||||
stackitem.EncodeBinaryProtected(it, w)
|
||||
}
|
||||
w.WriteArray(aer.Events)
|
||||
w.WriteVarUint(uint64(len(aer.Events)))
|
||||
for i := range aer.Events {
|
||||
aer.Events[i].EncodeBinary(w)
|
||||
}
|
||||
w.WriteVarBytes([]byte(aer.FaultException))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,31 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func BenchmarkAppExecResult_EncodeBinary(b *testing.B) {
|
||||
aer := &AppExecResult{
|
||||
Container: random.Uint256(),
|
||||
Execution: Execution{
|
||||
Trigger: trigger.Application,
|
||||
VMState: vm.HaltState,
|
||||
GasConsumed: 12345,
|
||||
Stack: []stackitem.Item{},
|
||||
Events: []NotificationEvent{{
|
||||
ScriptHash: random.Uint160(),
|
||||
Name: "Event",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewBool(true)}),
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
w := io.NewBufBinWriter()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
w.Reset()
|
||||
aer.EncodeBinary(w.BinWriter)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeNotificationEvent(t *testing.T) {
|
||||
event := &NotificationEvent{
|
||||
ScriptHash: random.Uint160(),
|
||||
|
|
|
@ -53,3 +53,14 @@ func BenchmarkDecodeFromBytes(t *testing.B) {
|
|||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTransaction_Bytes(b *testing.B) {
|
||||
tx, err := NewTransactionFromBytes(benchTx)
|
||||
require.NoError(b, err)
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = tx.Bytes()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,7 +203,10 @@ func (t *Transaction) DecodeBinary(br *io.BinReader) {
|
|||
// EncodeBinary implements Serializable interface.
|
||||
func (t *Transaction) EncodeBinary(bw *io.BinWriter) {
|
||||
t.encodeHashableFields(bw)
|
||||
bw.WriteArray(t.Scripts)
|
||||
bw.WriteVarUint(uint64(len(t.Scripts)))
|
||||
for i := range t.Scripts {
|
||||
t.Scripts[i].EncodeBinary(bw)
|
||||
}
|
||||
}
|
||||
|
||||
// encodeHashableFields encodes the fields that are not used for
|
||||
|
@ -218,8 +221,14 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
|
|||
bw.WriteU64LE(uint64(t.SystemFee))
|
||||
bw.WriteU64LE(uint64(t.NetworkFee))
|
||||
bw.WriteU32LE(t.ValidUntilBlock)
|
||||
bw.WriteArray(t.Signers)
|
||||
bw.WriteArray(t.Attributes)
|
||||
bw.WriteVarUint(uint64(len(t.Signers)))
|
||||
for i := range t.Signers {
|
||||
t.Signers[i].EncodeBinary(bw)
|
||||
}
|
||||
bw.WriteVarUint(uint64(len(t.Attributes)))
|
||||
for i := range t.Attributes {
|
||||
t.Attributes[i].EncodeBinary(bw)
|
||||
}
|
||||
bw.WriteVarBytes(t.Script)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue