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 benchmarks
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
2026-06-02 11:39:52 -07:00
|
|
|
"github.com/luxfi/crypto/hash"
|
2026-04-13 03:45:21 -07:00
|
|
|
"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 benchmarks signature verification
|
|
|
|
|
func BenchmarkVerifySignature(b *testing.B) {
|
|
|
|
|
// This is a placeholder for actual signature verification
|
|
|
|
|
// In real implementation, this would use actual crypto operations
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|