wire: Add several decode benchmarks. (#682)
This adds decode benchmarks for several of the messages that profiling has identified to cause a lot of allocations in addition to those that already exist. By adding these benchmarks, it makes it easier to get allocation and speed statistics which can in turn be used to compare future improvements. The following bencharmarks have been added: DecodeGetHeaders, DecodeHeaders, DecodeGetBlocks, DecodeAddr, DecodeInv, DecodeNotFound, and DecodeMerkleBlock For reference, here is the benchmark data as of this commit. DecodeGetHeaders 93261 ns/op 24120 B/op 1004 allocs/op DecodeHeaders 2071263 ns/op 368399 B/op 18002 allocs/op DecodeGetBlocks 92486 ns/op 24120 B/op 1004 allocs/op DecodeAddr 850608 ns/op 136202 B/op 9002 allocs/op DecodeInv 17107172 ns/op 3601447 B/op 150004 allocs/op DecodeNotFound 17522225 ns/op 3601444 B/op 150004 allocs/op DecodeMerkleBlock 21062 ns/op 5192 B/op 222 allocs/op
This commit is contained in:
parent
e7ddaa468e
commit
b14032487f
1 changed files with 219 additions and 4 deletions
|
@ -7,7 +7,9 @@ package wire
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/bzip2"
|
"compress/bzip2"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -432,6 +434,221 @@ func BenchmarkWriteBlockHeader(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeGetHeaders performs a benchmark on how long it takes to
|
||||||
|
// decode a getheaders message with the maximum number of block locator hashes.
|
||||||
|
func BenchmarkDecodeGetHeaders(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of block locators.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgGetHeaders
|
||||||
|
for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddBlockLocatorHash(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgGetHeaders.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgGetHeaders
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeHeaders performs a benchmark on how long it takes to
|
||||||
|
// decode a headers message with the maximum number of headers.
|
||||||
|
func BenchmarkDecodeHeaders(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of headers.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgHeaders
|
||||||
|
for i := 0; i < MaxBlockHeadersPerMsg; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddBlockHeader(NewBlockHeader(hash, hash, 0, uint32(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgHeaders.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgHeaders
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeGetBlocks performs a benchmark on how long it takes to
|
||||||
|
// decode a getblocks message with the maximum number of block locator hashes.
|
||||||
|
func BenchmarkDecodeGetBlocks(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of block locators.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgGetBlocks
|
||||||
|
for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddBlockLocatorHash(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgGetBlocks.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgGetBlocks
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeAddr performs a benchmark on how long it takes to decode an
|
||||||
|
// addr message with the maximum number of addresses.
|
||||||
|
func BenchmarkDecodeAddr(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of addresses.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
ip := net.ParseIP("127.0.0.1")
|
||||||
|
ma := NewMsgAddr()
|
||||||
|
for port := uint16(0); port < MaxAddrPerMsg; port++ {
|
||||||
|
ma.AddAddress(NewNetAddressIPPort(ip, port, SFNodeNetwork))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := ma.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgAddr.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgAddr
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeInv performs a benchmark on how long it takes to decode an inv
|
||||||
|
// message with the maximum number of entries.
|
||||||
|
func BenchmarkDecodeInv(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of entries.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgInv
|
||||||
|
for i := 0; i < MaxInvPerMsg; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddInvVect(NewInvVect(InvTypeBlock, hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgInv.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgInv
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeNotFound performs a benchmark on how long it takes to decode
|
||||||
|
// a notfound message with the maximum number of entries.
|
||||||
|
func BenchmarkDecodeNotFound(b *testing.B) {
|
||||||
|
// Create a message with the maximum number of entries.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgNotFound
|
||||||
|
for i := 0; i < MaxInvPerMsg; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddInvVect(NewInvVect(InvTypeBlock, hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgNotFound.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgNotFound
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkDecodeMerkleBlock performs a benchmark on how long it takes to
|
||||||
|
// decode a reasonably sized merkleblock message.
|
||||||
|
func BenchmarkDecodeMerkleBlock(b *testing.B) {
|
||||||
|
// Create a message with random data.
|
||||||
|
pver := ProtocolVersion
|
||||||
|
var m MsgMerkleBlock
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", 10000))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.Header = *NewBlockHeader(hash, hash, 0, uint32(10000))
|
||||||
|
for i := 0; i < 105; i++ {
|
||||||
|
hash, err := NewShaHashFromStr(fmt.Sprintf("%x", i))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
m.AddTxHash(hash)
|
||||||
|
if i%8 == 0 {
|
||||||
|
m.Flags = append(m.Flags, uint8(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize it so the bytes are available to test the decode below.
|
||||||
|
var bb bytes.Buffer
|
||||||
|
if err := m.BtcEncode(&bb, pver); err != nil {
|
||||||
|
b.Fatalf("MsgMerkleBlock.BtcEncode: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
buf := bb.Bytes()
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
var msg MsgMerkleBlock
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Seek(0, 0)
|
||||||
|
msg.BtcDecode(r, pver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BenchmarkTxSha performs a benchmark on how long it takes to hash a
|
// BenchmarkTxSha performs a benchmark on how long it takes to hash a
|
||||||
// transaction.
|
// transaction.
|
||||||
func BenchmarkTxSha(b *testing.B) {
|
func BenchmarkTxSha(b *testing.B) {
|
||||||
|
@ -443,15 +660,14 @@ func BenchmarkTxSha(b *testing.B) {
|
||||||
// BenchmarkDoubleSha256 performs a benchmark on how long it takes to perform a
|
// BenchmarkDoubleSha256 performs a benchmark on how long it takes to perform a
|
||||||
// double sha 256 returning a byte slice.
|
// double sha 256 returning a byte slice.
|
||||||
func BenchmarkDoubleSha256(b *testing.B) {
|
func BenchmarkDoubleSha256(b *testing.B) {
|
||||||
b.StopTimer()
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := genesisCoinbaseTx.Serialize(&buf); err != nil {
|
if err := genesisCoinbaseTx.Serialize(&buf); err != nil {
|
||||||
b.Errorf("Serialize: unexpected error: %v", err)
|
b.Errorf("Serialize: unexpected error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txBytes := buf.Bytes()
|
txBytes := buf.Bytes()
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_ = DoubleSha256(txBytes)
|
_ = DoubleSha256(txBytes)
|
||||||
}
|
}
|
||||||
|
@ -460,15 +676,14 @@ func BenchmarkDoubleSha256(b *testing.B) {
|
||||||
// BenchmarkDoubleSha256SH performs a benchmark on how long it takes to perform
|
// BenchmarkDoubleSha256SH performs a benchmark on how long it takes to perform
|
||||||
// a double sha 256 returning a ShaHash.
|
// a double sha 256 returning a ShaHash.
|
||||||
func BenchmarkDoubleSha256SH(b *testing.B) {
|
func BenchmarkDoubleSha256SH(b *testing.B) {
|
||||||
b.StopTimer()
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := genesisCoinbaseTx.Serialize(&buf); err != nil {
|
if err := genesisCoinbaseTx.Serialize(&buf); err != nil {
|
||||||
b.Errorf("Serialize: unexpected error: %v", err)
|
b.Errorf("Serialize: unexpected error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txBytes := buf.Bytes()
|
txBytes := buf.Bytes()
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_ = DoubleSha256SH(txBytes)
|
_ = DoubleSha256SH(txBytes)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue