github.com/MetalBlockchain/metalgo@v1.11.9/message/messages_benchmark_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package message
     5  
     6  import (
     7  	"net"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/stretchr/testify/require"
    14  	"google.golang.org/protobuf/proto"
    15  
    16  	"github.com/MetalBlockchain/metalgo/ids"
    17  	"github.com/MetalBlockchain/metalgo/proto/pb/p2p"
    18  	"github.com/MetalBlockchain/metalgo/utils/compression"
    19  	"github.com/MetalBlockchain/metalgo/utils/logging"
    20  )
    21  
    22  var (
    23  	dummyNodeID             = ids.EmptyNodeID
    24  	dummyOnFinishedHandling = func() {}
    25  )
    26  
    27  // Benchmarks marshal-ing "Handshake" message.
    28  //
    29  // e.g.,
    30  //
    31  //	$ go install -v golang.org/x/tools/cmd/benchcmp@latest
    32  //	$ go install -v golang.org/x/perf/cmd/benchstat@latest
    33  //
    34  //	$ go test -run=NONE -bench=BenchmarkMarshalHandshake > /tmp/cpu.before.txt
    35  //	$ USE_BUILDER=true go test -run=NONE -bench=BenchmarkMarshalHandshake > /tmp/cpu.after.txt
    36  //	$ benchcmp /tmp/cpu.before.txt /tmp/cpu.after.txt
    37  //	$ benchstat -alpha 0.03 -geomean /tmp/cpu.before.txt /tmp/cpu.after.txt
    38  //
    39  //	$ go test -run=NONE -bench=BenchmarkMarshalHandshake -benchmem > /tmp/mem.before.txt
    40  //	$ USE_BUILDER=true go test -run=NONE -bench=BenchmarkMarshalHandshake -benchmem > /tmp/mem.after.txt
    41  //	$ benchcmp /tmp/mem.before.txt /tmp/mem.after.txt
    42  //	$ benchstat -alpha 0.03 -geomean /tmp/mem.before.txt /tmp/mem.after.txt
    43  func BenchmarkMarshalHandshake(b *testing.B) {
    44  	require := require.New(b)
    45  
    46  	id := ids.GenerateTestID()
    47  	msg := p2p.Message{
    48  		Message: &p2p.Message_Handshake{
    49  			Handshake: &p2p.Handshake{
    50  				NetworkId:      uint32(1337),
    51  				MyTime:         uint64(time.Now().Unix()),
    52  				IpAddr:         []byte(net.IPv4(1, 2, 3, 4).To16()),
    53  				IpPort:         0,
    54  				IpSigningTime:  uint64(time.Now().Unix()),
    55  				IpNodeIdSig:    []byte{'y', 'e', 'e', 't'},
    56  				TrackedSubnets: [][]byte{id[:]},
    57  				IpBlsSig:       []byte{'y', 'e', 'e', 't', '2'},
    58  			},
    59  		},
    60  	}
    61  	msgLen := proto.Size(&msg)
    62  
    63  	useBuilder := os.Getenv("USE_BUILDER") != ""
    64  
    65  	codec, err := newMsgBuilder(logging.NoLog{}, prometheus.NewRegistry(), 10*time.Second)
    66  	require.NoError(err)
    67  
    68  	b.Logf("proto length %d-byte (use builder %v)", msgLen, useBuilder)
    69  
    70  	b.ResetTimer()
    71  	for i := 0; i < b.N; i++ {
    72  		if useBuilder {
    73  			_, err = codec.createOutbound(&msg, compression.TypeNone, false)
    74  		} else {
    75  			_, err = proto.Marshal(&msg)
    76  		}
    77  		require.NoError(err)
    78  	}
    79  }
    80  
    81  // Benchmarks unmarshal-ing "Version" message.
    82  //
    83  // e.g.,
    84  //
    85  //	$ go install -v golang.org/x/tools/cmd/benchcmp@latest
    86  //	$ go install -v golang.org/x/perf/cmd/benchstat@latest
    87  //
    88  //	$ go test -run=NONE -bench=BenchmarkUnmarshalHandshake > /tmp/cpu.before.txt
    89  //	$ USE_BUILDER=true go test -run=NONE -bench=BenchmarkUnmarshalHandshake > /tmp/cpu.after.txt
    90  //	$ benchcmp /tmp/cpu.before.txt /tmp/cpu.after.txt
    91  //	$ benchstat -alpha 0.03 -geomean /tmp/cpu.before.txt /tmp/cpu.after.txt
    92  //
    93  //	$ go test -run=NONE -bench=BenchmarkUnmarshalHandshake -benchmem > /tmp/mem.before.txt
    94  //	$ USE_BUILDER=true go test -run=NONE -bench=BenchmarkUnmarshalHandshake -benchmem > /tmp/mem.after.txt
    95  //	$ benchcmp /tmp/mem.before.txt /tmp/mem.after.txt
    96  //	$ benchstat -alpha 0.03 -geomean /tmp/mem.before.txt /tmp/mem.after.txt
    97  func BenchmarkUnmarshalHandshake(b *testing.B) {
    98  	require := require.New(b)
    99  
   100  	b.StopTimer()
   101  
   102  	id := ids.GenerateTestID()
   103  	msg := p2p.Message{
   104  		Message: &p2p.Message_Handshake{
   105  			Handshake: &p2p.Handshake{
   106  				NetworkId:      uint32(1337),
   107  				MyTime:         uint64(time.Now().Unix()),
   108  				IpAddr:         []byte(net.IPv4(1, 2, 3, 4).To16()),
   109  				IpPort:         0,
   110  				IpSigningTime:  uint64(time.Now().Unix()),
   111  				IpNodeIdSig:    []byte{'y', 'e', 'e', 't'},
   112  				TrackedSubnets: [][]byte{id[:]},
   113  				IpBlsSig:       []byte{'y', 'e', 'e', 't', '2'},
   114  			},
   115  		},
   116  	}
   117  
   118  	rawMsg, err := proto.Marshal(&msg)
   119  	require.NoError(err)
   120  
   121  	useBuilder := os.Getenv("USE_BUILDER") != ""
   122  	codec, err := newMsgBuilder(logging.NoLog{}, prometheus.NewRegistry(), 10*time.Second)
   123  	require.NoError(err)
   124  
   125  	b.StartTimer()
   126  	for i := 0; i < b.N; i++ {
   127  		if useBuilder {
   128  			_, err = codec.parseInbound(rawMsg, dummyNodeID, dummyOnFinishedHandling)
   129  			require.NoError(err)
   130  		} else {
   131  			var msg p2p.Message
   132  			require.NoError(proto.Unmarshal(rawMsg, &msg))
   133  		}
   134  	}
   135  }