Merge pull request #546 from nspcc-dev/write-optimizations

Write optimizations
This commit is contained in:
Roman Khimov 2019-12-06 19:40:38 +03:00 committed by GitHub
commit e4d821f32d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 59 additions and 50 deletions

View file

@ -19,7 +19,7 @@ func emit(w *io.BinWriter, instr opcode.Opcode, b []byte) {
// emitOpcode emits a single VM Instruction the given buffer. // emitOpcode emits a single VM Instruction the given buffer.
func emitOpcode(w *io.BinWriter, instr opcode.Opcode) { func emitOpcode(w *io.BinWriter, instr opcode.Opcode) {
w.WriteLE(byte(instr)) w.WriteBytes([]byte{byte(instr)})
} }
// emitBool emits a bool type the given buffer. // emitBool emits a bool type the given buffer.

View file

@ -18,7 +18,7 @@ var _ payload.Commit = (*commit)(nil)
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (c *commit) EncodeBinary(w *io.BinWriter) { func (c *commit) EncodeBinary(w *io.BinWriter) {
w.WriteBE(c.signature) w.WriteBytes(c.signature[:])
} }
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.

View file

@ -162,7 +162,7 @@ func (p *Payload) SetHeight(h uint32) {
// EncodeBinaryUnsigned writes payload to w excluding signature. // EncodeBinaryUnsigned writes payload to w excluding signature.
func (p Payload) EncodeBinaryUnsigned(w *io.BinWriter) { func (p Payload) EncodeBinaryUnsigned(w *io.BinWriter) {
w.WriteLE(p.version) w.WriteLE(p.version)
w.WriteBE(p.prevHash[:]) w.WriteBytes(p.prevHash[:])
w.WriteLE(p.height) w.WriteLE(p.height)
w.WriteLE(p.validatorIndex) w.WriteLE(p.validatorIndex)
w.WriteLE(p.timestamp) w.WriteLE(p.timestamp)
@ -254,7 +254,7 @@ func (p *Payload) DecodeBinary(r *io.BinReader) {
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (m *message) EncodeBinary(w *io.BinWriter) { func (m *message) EncodeBinary(w *io.BinWriter) {
w.WriteLE(byte(m.Type)) w.WriteBytes([]byte{byte(m.Type)})
w.WriteLE(m.ViewNumber) w.WriteLE(m.ViewNumber)
m.payload.EncodeBinary(w) m.payload.EncodeBinary(w)
} }

View file

@ -22,7 +22,7 @@ var _ payload.PrepareRequest = (*prepareRequest)(nil)
func (p *prepareRequest) EncodeBinary(w *io.BinWriter) { func (p *prepareRequest) EncodeBinary(w *io.BinWriter) {
w.WriteLE(p.timestamp) w.WriteLE(p.timestamp)
w.WriteLE(p.nonce) w.WriteLE(p.nonce)
w.WriteBE(p.nextConsensus[:]) w.WriteBytes(p.nextConsensus[:])
w.WriteArray(p.transactionHashes) w.WriteArray(p.transactionHashes)
p.minerTx.EncodeBinary(w) p.minerTx.EncodeBinary(w)
} }

View file

@ -15,7 +15,7 @@ var _ payload.PrepareResponse = (*prepareResponse)(nil)
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (p *prepareResponse) EncodeBinary(w *io.BinWriter) { func (p *prepareResponse) EncodeBinary(w *io.BinWriter) {
w.WriteBE(p.preparationHash[:]) w.WriteBytes(p.preparationHash[:])
} }
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.

View file

@ -80,7 +80,7 @@ func (m *recoveryMessage) EncodeBinary(w *io.BinWriter) {
w.WriteVarUint(0) w.WriteVarUint(0)
} else { } else {
w.WriteVarUint(util.Uint256Size) w.WriteVarUint(util.Uint256Size)
w.WriteBE(m.preparationHash[:]) w.WriteBytes(m.preparationHash[:])
} }
} }
@ -116,7 +116,7 @@ func (p *commitCompact) DecodeBinary(r *io.BinReader) {
func (p *commitCompact) EncodeBinary(w *io.BinWriter) { func (p *commitCompact) EncodeBinary(w *io.BinWriter) {
w.WriteLE(p.ViewNumber) w.WriteLE(p.ViewNumber)
w.WriteLE(p.ValidatorIndex) w.WriteLE(p.ValidatorIndex)
w.WriteBE(p.Signature) w.WriteBytes(p.Signature[:])
w.WriteVarBytes(p.InvocationScript) w.WriteVarBytes(p.InvocationScript)
} }

View file

@ -121,13 +121,13 @@ func (s *AccountState) DecodeBinary(br *io.BinReader) {
// EncodeBinary encodes AccountState to the given BinWriter. // EncodeBinary encodes AccountState to the given BinWriter.
func (s *AccountState) EncodeBinary(bw *io.BinWriter) { func (s *AccountState) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(s.Version) bw.WriteLE(s.Version)
bw.WriteLE(s.ScriptHash) bw.WriteBytes(s.ScriptHash[:])
bw.WriteLE(s.IsFrozen) bw.WriteLE(s.IsFrozen)
bw.WriteArray(s.Votes) bw.WriteArray(s.Votes)
bw.WriteVarUint(uint64(len(s.Balances))) bw.WriteVarUint(uint64(len(s.Balances)))
for k, v := range s.Balances { for k, v := range s.Balances {
bw.WriteLE(k) bw.WriteBytes(k[:])
bw.WriteArray(v) bw.WriteArray(v)
} }
} }

View file

@ -73,19 +73,19 @@ func (a *AssetState) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (a *AssetState) EncodeBinary(bw *io.BinWriter) { func (a *AssetState) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(a.ID) bw.WriteBytes(a.ID[:])
bw.WriteLE(a.AssetType) bw.WriteLE(a.AssetType)
bw.WriteString(a.Name) bw.WriteString(a.Name)
bw.WriteLE(a.Amount) bw.WriteLE(a.Amount)
bw.WriteLE(a.Available) bw.WriteLE(a.Available)
bw.WriteLE(a.Precision) bw.WriteLE(a.Precision)
bw.WriteLE(a.FeeMode) bw.WriteLE(a.FeeMode)
bw.WriteLE(a.FeeAddress) bw.WriteBytes(a.FeeAddress[:])
a.Owner.EncodeBinary(bw) a.Owner.EncodeBinary(bw)
bw.WriteLE(a.Admin) bw.WriteBytes(a.Admin[:])
bw.WriteLE(a.Issuer) bw.WriteBytes(a.Issuer[:])
bw.WriteLE(a.Expiration) bw.WriteLE(a.Expiration)
bw.WriteLE(a.IsFrozen) bw.WriteLE(a.IsFrozen)
} }

View file

@ -111,12 +111,12 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
func (b *Block) Trim() ([]byte, error) { func (b *Block) Trim() ([]byte, error) {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
b.encodeHashableFields(buf.BinWriter) b.encodeHashableFields(buf.BinWriter)
buf.WriteLE(uint8(1)) buf.WriteBytes([]byte{1})
b.Script.EncodeBinary(buf.BinWriter) b.Script.EncodeBinary(buf.BinWriter)
buf.WriteVarUint(uint64(len(b.Transactions))) buf.WriteVarUint(uint64(len(b.Transactions)))
for _, tx := range b.Transactions { for _, tx := range b.Transactions {
buf.WriteLE(tx.Hash()) tx.Hash().EncodeBinary(buf.BinWriter)
} }
if buf.Err != nil { if buf.Err != nil {
return nil, buf.Err return nil, buf.Err

View file

@ -87,7 +87,7 @@ func (b *BlockBase) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface // EncodeBinary implements Serializable interface
func (b *BlockBase) EncodeBinary(bw *io.BinWriter) { func (b *BlockBase) EncodeBinary(bw *io.BinWriter) {
b.encodeHashableFields(bw) b.encodeHashableFields(bw)
bw.WriteLE(uint8(1)) bw.WriteBytes([]byte{1})
b.Script.EncodeBinary(bw) b.Script.EncodeBinary(bw)
} }
@ -116,12 +116,12 @@ func (b *BlockBase) createHash() {
// see Hash() for more information about the fields. // see Hash() for more information about the fields.
func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) { func (b *BlockBase) encodeHashableFields(bw *io.BinWriter) {
bw.WriteLE(b.Version) bw.WriteLE(b.Version)
bw.WriteLE(b.PrevHash) bw.WriteBytes(b.PrevHash[:])
bw.WriteLE(b.MerkleRoot) bw.WriteBytes(b.MerkleRoot[:])
bw.WriteLE(b.Timestamp) bw.WriteLE(b.Timestamp)
bw.WriteLE(b.Index) bw.WriteLE(b.Index)
bw.WriteLE(b.ConsensusData) bw.WriteLE(b.ConsensusData)
bw.WriteLE(b.NextConsensus) bw.WriteBytes(b.NextConsensus[:])
} }
// decodeHashableFields decodes the fields used for hashing. // decodeHashableFields decodes the fields used for hashing.

View file

@ -403,16 +403,17 @@ func (bc *Blockchain) storeBlock(block *Block) error {
if balancesLen <= 1 { if balancesLen <= 1 {
delete(account.Balances, prevTXOutput.AssetID) delete(account.Balances, prevTXOutput.AssetID)
} else { } else {
var gotTx bool var index = -1
for index, balance := range account.Balances[prevTXOutput.AssetID] { for i, balance := range account.Balances[prevTXOutput.AssetID] {
if !gotTx && balance.Tx.Equals(input.PrevHash) && balance.Index == input.PrevIndex { if balance.Tx.Equals(input.PrevHash) && balance.Index == input.PrevIndex {
gotTx = true index = i
} break
if gotTx && index+1 < balancesLen {
account.Balances[prevTXOutput.AssetID][index] = account.Balances[prevTXOutput.AssetID][index+1]
} }
} }
account.Balances[prevTXOutput.AssetID] = account.Balances[prevTXOutput.AssetID][:balancesLen-1] if index >= 0 {
copy(account.Balances[prevTXOutput.AssetID][index:], account.Balances[prevTXOutput.AssetID][index+1:])
account.Balances[prevTXOutput.AssetID] = account.Balances[prevTXOutput.AssetID][:balancesLen-1]
}
} }
} }
} }

View file

@ -29,5 +29,5 @@ func (h *Header) DecodeBinary(r *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (h *Header) EncodeBinary(w *io.BinWriter) { func (h *Header) EncodeBinary(w *io.BinWriter) {
h.BlockBase.EncodeBinary(w) h.BlockBase.EncodeBinary(w)
w.WriteLE(uint8(0)) w.WriteBytes([]byte{0})
} }

View file

@ -57,7 +57,7 @@ func getAppExecResultFromStore(s storage.Store, hash util.Uint256) (*AppExecResu
// EncodeBinary implements the Serializable interface. // EncodeBinary implements the Serializable interface.
func (ne NotificationEvent) EncodeBinary(w *io.BinWriter) { func (ne NotificationEvent) EncodeBinary(w *io.BinWriter) {
w.WriteLE(ne.ScriptHash) w.WriteBytes(ne.ScriptHash[:])
vm.EncodeBinaryStackItem(ne.Item, w) vm.EncodeBinaryStackItem(ne.Item, w)
} }
@ -69,7 +69,7 @@ func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
// EncodeBinary implements the Serializable interface. // EncodeBinary implements the Serializable interface.
func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) { func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) {
w.WriteLE(aer.TxHash) w.WriteBytes(aer.TxHash[:])
w.WriteArray(aer.Events) w.WriteArray(aer.Events)
} }

View file

@ -93,7 +93,7 @@ func (s *SpentCoinState) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) { func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(s.txHash) bw.WriteBytes(s.txHash[:])
bw.WriteLE(s.txHeight) bw.WriteLE(s.txHeight)
bw.WriteVarUint(uint64(len(s.items))) bw.WriteVarUint(uint64(len(s.items)))
for k, v := range s.items { for k, v := range s.items {

View file

@ -22,6 +22,6 @@ func (in *Input) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (in *Input) EncodeBinary(bw *io.BinWriter) { func (in *Input) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(in.PrevHash) bw.WriteBytes(in.PrevHash[:])
bw.WriteLE(in.PrevIndex) bw.WriteLE(in.PrevIndex)
} }

View file

@ -42,9 +42,9 @@ func (out *Output) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (out *Output) EncodeBinary(bw *io.BinWriter) { func (out *Output) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(out.AssetID) bw.WriteBytes(out.AssetID[:])
bw.WriteLE(out.Amount) bw.WriteLE(out.Amount)
bw.WriteLE(out.ScriptHash) bw.WriteBytes(out.ScriptHash[:])
} }
// MarshalJSON implements the Marshaler interface. // MarshalJSON implements the Marshaler interface.

View file

@ -50,5 +50,5 @@ func (tx *RegisterTX) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(tx.Amount) bw.WriteLE(tx.Amount)
bw.WriteLE(tx.Precision) bw.WriteLE(tx.Precision)
bw.WriteBytes(tx.Owner.Bytes()) bw.WriteBytes(tx.Owner.Bytes())
bw.WriteLE(tx.Admin) bw.WriteBytes(tx.Admin[:])
} }

View file

@ -92,7 +92,7 @@ func (u UnspentCoins) commit(store storage.Store) error {
func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) { func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) {
bw.WriteVarUint(uint64(len(s.states))) bw.WriteVarUint(uint64(len(s.states)))
for _, state := range s.states { for _, state := range s.states {
bw.WriteLE(byte(state)) bw.WriteBytes([]byte{byte(state)})
} }
} }

View file

@ -95,13 +95,16 @@ func (w *BinWriter) WriteVarUint(val uint64) {
// WriteBytes writes a variable byte into the underlying io.Writer without prefix. // WriteBytes writes a variable byte into the underlying io.Writer without prefix.
func (w *BinWriter) WriteBytes(b []byte) { func (w *BinWriter) WriteBytes(b []byte) {
w.WriteLE(b) if w.Err != nil {
return
}
_, w.Err = w.w.Write(b)
} }
// WriteVarBytes writes a variable length byte array into the underlying io.Writer. // WriteVarBytes writes a variable length byte array into the underlying io.Writer.
func (w *BinWriter) WriteVarBytes(b []byte) { func (w *BinWriter) WriteVarBytes(b []byte) {
w.WriteVarUint(uint64(len(b))) w.WriteVarUint(uint64(len(b)))
w.WriteLE(b) w.WriteBytes(b)
} }
// WriteString writes a variable length string into the underlying io.Writer. // WriteString writes a variable length string into the underlying io.Writer.

View file

@ -210,6 +210,11 @@ func TestWriteBytes(t *testing.T) {
buf := bw.Bytes() buf := bw.Bytes()
assert.Equal(t, 4, len(buf)) assert.Equal(t, 4, len(buf))
assert.Equal(t, byte(0xde), buf[0]) assert.Equal(t, byte(0xde), buf[0])
bw = NewBufBinWriter()
bw.Err = errors.New("smth bad")
bw.WriteBytes(bin)
assert.Equal(t, 0, bw.Len())
} }
type testSerializable uint16 type testSerializable uint16

View file

@ -213,7 +213,7 @@ func (m *Message) decodePayload(br *io.BinReader) error {
// Encode encodes a Message to any given BinWriter. // Encode encodes a Message to any given BinWriter.
func (m *Message) Encode(br *io.BinWriter) error { func (m *Message) Encode(br *io.BinWriter) error {
br.WriteLE(m.Magic) br.WriteLE(m.Magic)
br.WriteLE(m.Command) br.WriteBytes(m.Command[:])
br.WriteLE(m.Length) br.WriteLE(m.Length)
br.WriteLE(m.Checksum) br.WriteLE(m.Checksum)
if m.Payload != nil { if m.Payload != nil {

View file

@ -39,7 +39,7 @@ func (p *AddressAndTime) DecodeBinary(br *io.BinReader) {
func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) { func (p *AddressAndTime) EncodeBinary(bw *io.BinWriter) {
bw.WriteLE(p.Timestamp) bw.WriteLE(p.Timestamp)
bw.WriteLE(p.Services) bw.WriteLE(p.Services)
bw.WriteBE(p.IP) bw.WriteBytes(p.IP[:])
bw.WriteBE(p.Port) bw.WriteBE(p.Port)
} }

View file

@ -30,5 +30,5 @@ func (p *GetBlocks) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) { func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) {
bw.WriteArray(p.HashStart) bw.WriteArray(p.HashStart)
bw.WriteLE(p.HashStop) bw.WriteBytes(p.HashStop[:])
} }

View file

@ -80,7 +80,7 @@ func (pt ParamType) MarshalJSON() ([]byte, error) {
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (pt ParamType) EncodeBinary(w *io.BinWriter) { func (pt ParamType) EncodeBinary(w *io.BinWriter) {
w.WriteLE(pt) w.WriteBytes([]byte{byte(pt)})
} }
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.

View file

@ -118,7 +118,7 @@ func (u Uint256) CompareTo(other Uint256) int { return bytes.Compare(u[:], other
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (u Uint256) EncodeBinary(w *io.BinWriter) { func (u Uint256) EncodeBinary(w *io.BinWriter) {
w.WriteBE(u) w.WriteBytes(u[:])
} }
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.

View file

@ -43,13 +43,13 @@ func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
switch t := item.(type) { switch t := item.(type) {
case *ByteArrayItem: case *ByteArrayItem:
w.WriteLE(byte(byteArrayT)) w.WriteBytes([]byte{byte(byteArrayT)})
w.WriteVarBytes(t.value) w.WriteVarBytes(t.value)
case *BoolItem: case *BoolItem:
w.WriteLE(byte(booleanT)) w.WriteBytes([]byte{byte(booleanT)})
w.WriteLE(t.value) w.WriteLE(t.value)
case *BigIntegerItem: case *BigIntegerItem:
w.WriteLE(byte(integerT)) w.WriteBytes([]byte{byte(integerT)})
w.WriteVarBytes(t.Bytes()) w.WriteVarBytes(t.Bytes())
case *InteropItem: case *InteropItem:
w.Err = errors.New("not supported") w.Err = errors.New("not supported")
@ -58,9 +58,9 @@ func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
_, isArray := t.(*ArrayItem) _, isArray := t.(*ArrayItem)
if isArray { if isArray {
w.WriteLE(byte(arrayT)) w.WriteBytes([]byte{byte(arrayT)})
} else { } else {
w.WriteLE(byte(structT)) w.WriteBytes([]byte{byte(structT)})
} }
arr := t.Value().([]StackItem) arr := t.Value().([]StackItem)
@ -71,7 +71,7 @@ func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
case *MapItem: case *MapItem:
seen[item] = true seen[item] = true
w.WriteLE(byte(mapT)) w.WriteBytes([]byte{byte(mapT)})
w.WriteVarUint(uint64(len(t.value))) w.WriteVarUint(uint64(len(t.value)))
for k, v := range t.value { for k, v := range t.value {
serializeItemTo(v, w, seen) serializeItemTo(v, w, seen)