2026-04-13 03:45:21 -07:00
|
|
|
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
|
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
|
|
|
|
|
|
package message
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"github.com/luxfi/metric"
|
|
|
|
|
"net"
|
|
|
|
|
"os"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
2026-06-02 11:39:52 -07:00
|
|
|
compression "github.com/luxfi/compress"
|
2026-04-13 03:45:21 -07:00
|
|
|
"github.com/luxfi/ids"
|
|
|
|
|
"github.com/luxfi/node/proto/p2p"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
dummyNodeID = ids.EmptyNodeID
|
|
|
|
|
dummyOnFinishedHandling = func() {}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Benchmarks marshal-ing "Handshake" message.
|
|
|
|
|
//
|
|
|
|
|
// e.g.,
|
|
|
|
|
//
|
|
|
|
|
// $ go install -v golang.org/x/tools/cmd/benchcmp@latest
|
|
|
|
|
// $ go install -v golang.org/x/perf/cmd/benchstat@latest
|
|
|
|
|
//
|
|
|
|
|
// $ go test -run=NONE -bench=BenchmarkMarshalHandshake > /tmp/cpu.before.txt
|
|
|
|
|
// $ USE_BUILDER=true go test -run=NONE -bench=BenchmarkMarshalHandshake > /tmp/cpu.after.txt
|
|
|
|
|
// $ benchcmp /tmp/cpu.before.txt /tmp/cpu.after.txt
|
|
|
|
|
// $ benchstat -alpha 0.03 -geomean /tmp/cpu.before.txt /tmp/cpu.after.txt
|
|
|
|
|
//
|
|
|
|
|
// $ go test -run=NONE -bench=BenchmarkMarshalHandshake -benchmem > /tmp/mem.before.txt
|
|
|
|
|
// $ USE_BUILDER=true go test -run=NONE -bench=BenchmarkMarshalHandshake -benchmem > /tmp/mem.after.txt
|
|
|
|
|
// $ benchcmp /tmp/mem.before.txt /tmp/mem.after.txt
|
|
|
|
|
// $ benchstat -alpha 0.03 -geomean /tmp/mem.before.txt /tmp/mem.after.txt
|
|
|
|
|
func BenchmarkMarshalHandshake(b *testing.B) {
|
|
|
|
|
require := require.New(b)
|
|
|
|
|
|
|
|
|
|
id := ids.GenerateTestID()
|
|
|
|
|
msg := p2p.Message{
|
|
|
|
|
Message: &p2p.Message_Handshake{
|
|
|
|
|
Handshake: &p2p.Handshake{
|
|
|
|
|
NetworkId: uint32(1337),
|
|
|
|
|
MyTime: uint64(time.Now().Unix()),
|
|
|
|
|
IpAddr: []byte(net.IPv4(1, 2, 3, 4).To16()),
|
|
|
|
|
IpPort: 0,
|
|
|
|
|
IpSigningTime: uint64(time.Now().Unix()),
|
|
|
|
|
IpNodeIdSig: []byte{'y', 'e', 'e', 't'},
|
|
|
|
|
TrackedNets: [][]byte{id[:]},
|
|
|
|
|
IpBlsSig: []byte{'y', 'e', 'e', 't', '2'},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
msgLen := p2p.Size(&msg)
|
|
|
|
|
|
|
|
|
|
useBuilder := os.Getenv("USE_BUILDER") != ""
|
|
|
|
|
|
|
|
|
|
codec, err := newMsgBuilder(metric.NewRegistry(), 10*time.Second)
|
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
|
|
b.Logf("proto length %d-byte (use builder %v)", msgLen, useBuilder)
|
|
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
if useBuilder {
|
|
|
|
|
_, err = codec.createOutbound(&msg, compression.TypeNone, false)
|
|
|
|
|
} else {
|
|
|
|
|
_, err = p2p.Marshal(&msg)
|
|
|
|
|
}
|
|
|
|
|
require.NoError(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Benchmarks unmarshal-ing "Version" message.
|
|
|
|
|
//
|
|
|
|
|
// e.g.,
|
|
|
|
|
//
|
|
|
|
|
// $ go install -v golang.org/x/tools/cmd/benchcmp@latest
|
|
|
|
|
// $ go install -v golang.org/x/perf/cmd/benchstat@latest
|
|
|
|
|
//
|
|
|
|
|
// $ go test -run=NONE -bench=BenchmarkUnmarshalHandshake > /tmp/cpu.before.txt
|
|
|
|
|
// $ USE_BUILDER=true go test -run=NONE -bench=BenchmarkUnmarshalHandshake > /tmp/cpu.after.txt
|
|
|
|
|
// $ benchcmp /tmp/cpu.before.txt /tmp/cpu.after.txt
|
|
|
|
|
// $ benchstat -alpha 0.03 -geomean /tmp/cpu.before.txt /tmp/cpu.after.txt
|
|
|
|
|
//
|
|
|
|
|
// $ go test -run=NONE -bench=BenchmarkUnmarshalHandshake -benchmem > /tmp/mem.before.txt
|
|
|
|
|
// $ USE_BUILDER=true go test -run=NONE -bench=BenchmarkUnmarshalHandshake -benchmem > /tmp/mem.after.txt
|
|
|
|
|
// $ benchcmp /tmp/mem.before.txt /tmp/mem.after.txt
|
|
|
|
|
// $ benchstat -alpha 0.03 -geomean /tmp/mem.before.txt /tmp/mem.after.txt
|
|
|
|
|
func BenchmarkUnmarshalHandshake(b *testing.B) {
|
|
|
|
|
require := require.New(b)
|
|
|
|
|
|
|
|
|
|
b.StopTimer()
|
|
|
|
|
|
|
|
|
|
id := ids.GenerateTestID()
|
|
|
|
|
msg := p2p.Message{
|
|
|
|
|
Message: &p2p.Message_Handshake{
|
|
|
|
|
Handshake: &p2p.Handshake{
|
|
|
|
|
NetworkId: uint32(1337),
|
|
|
|
|
MyTime: uint64(time.Now().Unix()),
|
|
|
|
|
IpAddr: []byte(net.IPv4(1, 2, 3, 4).To16()),
|
|
|
|
|
IpPort: 0,
|
|
|
|
|
IpSigningTime: uint64(time.Now().Unix()),
|
|
|
|
|
IpNodeIdSig: []byte{'y', 'e', 'e', 't'},
|
|
|
|
|
TrackedNets: [][]byte{id[:]},
|
|
|
|
|
IpBlsSig: []byte{'y', 'e', 'e', 't', '2'},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rawMsg, err := p2p.Marshal(&msg)
|
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
|
|
useBuilder := os.Getenv("USE_BUILDER") != ""
|
|
|
|
|
codec, err := newMsgBuilder(metric.NewRegistry(), 10*time.Second)
|
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
if useBuilder {
|
|
|
|
|
_, err = codec.parseInbound(rawMsg, dummyNodeID, dummyOnFinishedHandling)
|
|
|
|
|
require.NoError(err)
|
|
|
|
|
} else {
|
|
|
|
|
var msg p2p.Message
|
|
|
|
|
require.NoError(p2p.Unmarshal(rawMsg, &msg))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|