From 05e81184d9ee292d976e7b80a19a4ec988c20978 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 4 Jun 2020 20:30:28 +0200 Subject: [PATCH] Misc GC optimisations (#619) * uint256 in rlp * uint256 rather than big.Int in Transation * linters * more linters * still linters * Reduce garbage in writeUint256 * Experiment with GC in writeByteArray * Misc GC optimisations * unsafe experiment with writeByteArray --- common/dbutils/composite_keys.go | 7 ++++--- core/vm/gas_table.go | 1 + rlp/encode.go | 30 +++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/common/dbutils/composite_keys.go b/common/dbutils/composite_keys.go index c466e501b7c..29b14dec4e7 100644 --- a/common/dbutils/composite_keys.go +++ b/common/dbutils/composite_keys.go @@ -117,9 +117,10 @@ func ParseCompositeStorageKey(compositeKey []byte) (common.Hash, uint64, common. // AddrHash + incarnation + KeyHash // For contract storage (for plain state) func PlainGenerateCompositeStorageKey(address common.Address, incarnation uint64, key common.Hash) []byte { - compositeKey := make([]byte, 0, common.AddressLength+8+common.HashLength) - compositeKey = append(compositeKey, PlainGenerateStoragePrefix(address, incarnation)...) - compositeKey = append(compositeKey, key[:]...) + compositeKey := make([]byte, common.AddressLength+8+common.HashLength) + copy(compositeKey, address[:]) + binary.BigEndian.PutUint64(compositeKey[common.AddressLength:], ^incarnation) + copy(compositeKey[common.AddressLength+8:], key[:]) return compositeKey } diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index f52029362e0..4aa186dbc53 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -193,6 +193,7 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m if current.Eq(value) { // noop (1) return params.SstoreNoopGasEIP2200, nil } + var original uint256.Int evm.IntraBlockState.GetCommittedState(contract.Address(), &key, &original) if original == current { diff --git a/rlp/encode.go b/rlp/encode.go index 3e2fece53d2..f732cf9e4d8 100644 --- a/rlp/encode.go +++ b/rlp/encode.go @@ -22,6 +22,7 @@ import ( "math/big" "reflect" "sync" + "unsafe" "github.com/holiman/uint256" ) @@ -114,10 +115,10 @@ func EncodeToReader(val interface{}) (size int, r io.Reader, err error) { } type encbuf struct { - str []byte // string data, contains everything except list headers - lheads []*listhead // all list headers - lhsize int // sum of sizes of all encoded list headers - sizebuf []byte // 9-byte auxiliary buffer for uint encoding + str []byte // string data, contains everything except list headers + lheads []listhead // all list headers + lhsize int // sum of sizes of all encoded list headers + sizebuf []byte // 9-byte auxiliary buffer for uint encoding } type listhead struct { @@ -203,13 +204,15 @@ func (w *encbuf) encodeString(b []byte) { } } -func (w *encbuf) list() *listhead { - lh := &listhead{offset: len(w.str), size: w.lhsize} +func (w *encbuf) list() int { + lh := listhead{offset: len(w.str), size: w.lhsize} + idx := len(w.lheads) w.lheads = append(w.lheads, lh) - return lh + return idx } -func (w *encbuf) listEnd(lh *listhead) { +func (w *encbuf) listEnd(idx int) { + lh := &w.lheads[idx] lh.size = w.size() - lh.offset - lh.size if lh.size < 56 { w.lhsize++ // length encoded into kind tag @@ -481,7 +484,16 @@ func writeByteArray(val reflect.Value, w *encbuf) error { pos := len(w.str) w.str = append(w.str, make([]byte, size)...) slice := w.str[pos:] - reflect.Copy(reflect.ValueOf(slice), val) + if val.CanAddr() { + sh := &reflect.SliceHeader{ + Data: val.UnsafeAddr(), + Len: size, + Cap: size, + } + copy(slice, *(*[]byte)(unsafe.Pointer(sh))) + } else { + reflect.Copy(reflect.ValueOf(slice), val) + } return nil }