Files
node/benchmarks/consensus_benchmark_test.go
zeekay 3183dab89c Make the whole module build and test again after the port
go list ./... returned nothing, so no package here could be built or tested and
the failure was invisible: one directory held a Go test beside fifteen .cpp
files, which makes it a Go package the toolchain then refuses. The generator
moves to the golden/ subdirectory the other two C++ chains already use.

That silence was hiding a package that does not compile. host/ calls
EnsureIdentity and identity.go defines LoadIdentity — a rename that happened on
one side — and it has no importers, because the Go host is cmd/luxd now. Deleted
rather than repaired: the thing it was a stand-in for arrived.

The operator tools came across too (backup, blscheck, ceremony, config,
genesishash, keytoaddr, pqkeygen, repair-proposervm, wire) plus benchmarks and
examples, so the package set now differs from the retired repo by exactly one
name: main/ is cmd/luxd.

Two tests were right and are now satisfied rather than silenced. The purity test
looked for ./main; it looks where the daemon lives. The chain-address test found
conformance/dex spelling /v1/chain by hand — but that is its own module on
purpose, since it links an EVM ABI and a signer the node must not carry, so it
cannot call Chain. The rule is about this module, and the walk now says so.
2026-09-07 17:16:26 -07:00

272 lines
5.4 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package benchmarks
import (
"context"
"testing"
"time"
"github.com/luxfi/crypto/hash"
"github.com/luxfi/ids"
"github.com/luxfi/log"
)
// BenchmarkHashingComputeHash256 benchmarks SHA256 hashing performance
func BenchmarkHashingComputeHash256(b *testing.B) {
data := make([]byte, 1024) // 1KB of data
for i := range data {
data[i] = byte(i % 256)
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = hash.ComputeHash256(data)
}
b.SetBytes(int64(len(data)))
}
// BenchmarkHashingComputeHash256Array benchmarks SHA256 array hashing
func BenchmarkHashingComputeHash256Array(b *testing.B) {
data := make([]byte, 32) // 32 bytes (common hash size)
for i := range data {
data[i] = byte(i)
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = hash.ComputeHash256Array(data)
}
b.SetBytes(int64(len(data)))
}
// BenchmarkIDGeneration benchmarks ID generation performance
func BenchmarkIDGeneration(b *testing.B) {
data := []byte("test data for ID generation")
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = ids.ID(hash.ComputeHash256(data))
}
}
// BenchmarkIDComparison benchmarks ID comparison operations
func BenchmarkIDComparison(b *testing.B) {
id1 := ids.GenerateTestID()
id2 := ids.GenerateTestID()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = id1.Compare(id2)
}
}
// BenchmarkIDString benchmarks ID string conversion
func BenchmarkIDString(b *testing.B) {
id := ids.GenerateTestID()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = id.String()
}
}
// BenchmarkIDFromString benchmarks parsing ID from string
func BenchmarkIDFromString(b *testing.B) {
idStr := ids.GenerateTestID().String()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = ids.FromString(idStr)
}
}
// BenchmarkVerifySignature times the loop around a signature verification, not
// the verification: the body below does arithmetic on the operand lengths and
// calls no crypto at all, so the number it reports is the harness floor.
func BenchmarkVerifySignature(b *testing.B) {
message := []byte("message to sign")
signature := make([]byte, 65) // typical signature size
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Simulate signature verification
_ = len(message) + len(signature)
}
}
// BenchmarkContextWithTimeout benchmarks context creation with timeout
func BenchmarkContextWithTimeout(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
cancel()
_ = ctx
}
}
// BenchmarkLoggerCreation benchmarks logger creation
func BenchmarkLoggerCreation(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = log.New()
}
}
// BenchmarkMapOperations benchmarks map operations commonly used in consensus
func BenchmarkMapOperations(b *testing.B) {
b.Run("Insert", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
m := make(map[ids.ID]bool)
for j := 0; j < 100; j++ {
m[ids.GenerateTestID()] = true
}
}
})
b.Run("Lookup", func(b *testing.B) {
m := make(map[ids.ID]bool)
keys := make([]ids.ID, 100)
for i := 0; i < 100; i++ {
id := ids.GenerateTestID()
keys[i] = id
m[id] = true
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = m[keys[i%100]]
}
})
b.Run("Delete", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
m := make(map[ids.ID]bool)
id := ids.GenerateTestID()
m[id] = true
delete(m, id)
}
})
}
// BenchmarkSliceOperations benchmarks slice operations
func BenchmarkSliceOperations(b *testing.B) {
b.Run("Append", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := make([]ids.ID, 0, 100)
for j := 0; j < 100; j++ {
s = append(s, ids.GenerateTestID())
}
}
})
b.Run("Copy", func(b *testing.B) {
src := make([]ids.ID, 100)
for i := range src {
src[i] = ids.GenerateTestID()
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
dst := make([]ids.ID, len(src))
copy(dst, src)
}
})
}
// BenchmarkChannelOperations benchmarks channel operations
func BenchmarkChannelOperations(b *testing.B) {
b.Run("Send", func(b *testing.B) {
ch := make(chan ids.ID, 100)
id := ids.GenerateTestID()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
select {
case ch <- id:
default:
// Channel full, drain it
<-ch
ch <- id
}
}
})
b.Run("Receive", func(b *testing.B) {
ch := make(chan ids.ID, 100)
id := ids.GenerateTestID()
for i := 0; i < 100; i++ {
ch <- id
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
select {
case <-ch:
ch <- id // Put it back
default:
}
}
})
}
// BenchmarkMessageSerialization benchmarks message serialization
func BenchmarkMessageSerialization(b *testing.B) {
type testMessage struct {
ID ids.ID
Height uint64
Timestamp time.Time
Data []byte
}
msg := testMessage{
ID: ids.GenerateTestID(),
Height: 1000000,
Timestamp: time.Now(),
Data: make([]byte, 256),
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Simulate serialization by accessing all fields
_ = msg.ID
_ = msg.Height
_ = msg.Timestamp
_ = msg.Data
}
}