Fast method for calculating transaction size
The transaction pool makes frequent use of the size of encoded transactions. Currently, we determine the size of a transaction by writing its encoded form to a buffer and returning the length of the buffer. Even though the transaction type has a custom MarshalSia
method, this is still wasteful; it is slow and puts pressure on the garbage collector.
The transaction type (and a few others) now have a MarshalSiaSize
method that returns the encoded size without encoding anything. These methods are essentially just iterated arithmetic, so they run very fast. Benchmarks for encoding types.GenesisBlock.Transactions[0]
:
BenchmarkTransactionMarshalSiaSize-4 2000000 918 ns/op 0 B/op 0 allocs/op
BenchmarkTransactionMarshalSiaLen-4 100000 12078 ns/op 11144 B/op 205 allocs/op
(BenchmarkTransactionMarshalSiaLen
calls len(encoding.Marshal(txn))
)
For small transactions, the effect is more pronounced: up to 40x faster.
I also added MarshalSia
methods for types.FileContract
and types.FileContractRevision
. This definitely speeds up the encoding of a transaction, but the effect isn't visible when encoding the genesis transaction (since it doesn't contain any file contracts).