ceremonyclient/node/consensus/reward/allocation_analysis_test.go
Cassandra Heart dbd95bd9e9
v2.1.0 (#439)
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete

* 2.1.0 main node rollup
2025-09-30 02:48:15 -05:00

153 lines
3.4 KiB
Go

package reward_test
import (
"math/big"
"testing"
"github.com/shopspring/decimal"
)
// These tests serve to determine the ideal profile for optimizing the PoMW
// evaluator
// BenchmarkPowWithPrecision tests the cost of the power operation
func BenchmarkPowWithPrecision(b *testing.B) {
testCases := []struct {
name string
shards uint64
}{
{"Shards_1", 1},
{"Shards_2", 2},
{"Shards_3", 3},
{"Shards_4", 4},
}
halfRat := big.NewRat(1, 2)
halfDecimal := decimal.NewFromBigRat(halfRat, 53)
for _, tc := range testCases {
b.Run(tc.name, func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
shardFactor := decimal.NewFromUint64(tc.shards)
_, err := shardFactor.PowWithPrecision(halfDecimal, 53)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// BenchmarkDecimalOperations tests individual decimal operations
func BenchmarkDecimalOperations(b *testing.B) {
// Setup test values
stateSize := decimal.NewFromUint64(2 * 1024 * 1024 * 1024)
worldStateBytes := decimal.NewFromUint64(4 * 1024 * 1024 * 1024)
basis := decimal.NewFromInt(4096000000000)
divisor := decimal.NewFromInt(2)
b.Run("NewFromUint64", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = decimal.NewFromUint64(2 * 1024 * 1024 * 1024)
}
})
b.Run("Div", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = stateSize.Div(worldStateBytes)
}
})
b.Run("Mul", func(b *testing.B) {
b.ReportAllocs()
factor := stateSize.Div(worldStateBytes)
for i := 0; i < b.N; i++ {
_ = factor.Mul(basis)
}
})
b.Run("BigInt_Conversion", func(b *testing.B) {
b.ReportAllocs()
result := basis.Div(divisor)
for i := 0; i < b.N; i++ {
_ = result.BigInt()
}
})
b.Run("Full_Calculation_Sequence", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Simulate one allocation calculation
factor := stateSize.Div(worldStateBytes)
result := factor.Mul(basis)
result = result.Div(divisor)
_ = result.BigInt()
}
})
}
// BenchmarkBigRatCreation tests BigRat creation cost
func BenchmarkBigRatCreation(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = big.NewRat(1, 2)
}
}
// BenchmarkSingleAllocationCalculation breaks down the cost of calculating one allocation
func BenchmarkSingleAllocationCalculation(b *testing.B) {
// Pre-computed values
worldStateBytes := uint64(4 * 1024 * 1024 * 1024)
basis := big.NewInt(4096000000000)
alloc := &struct {
Ring uint8
StateSize uint64
Shards uint64
}{
Ring: 1,
StateSize: 2 * 1024 * 1024 * 1024,
Shards: 2,
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 1. Calculate ring divisor
divisor := int64(1)
for j := uint8(0); j < alloc.Ring+1; j++ {
divisor *= 2
}
ringScaled := decimal.NewFromInt(divisor)
// 2. Calculate state size factor
factor := decimal.NewFromUint64(alloc.StateSize)
factor = factor.Div(decimal.NewFromUint64(worldStateBytes))
// 3. Apply basis
result := factor.Mul(decimal.NewFromBigInt(basis, 0))
result = result.Div(ringScaled)
// 4. Calculate shard factor (the expensive part)
shardFactor := decimal.NewFromUint64(alloc.Shards)
shardFactor, err := shardFactor.PowWithPrecision(
decimal.NewFromBigRat(big.NewRat(1, 2), 53),
53,
)
if err != nil {
b.Fatal(err)
}
// 5. Final division and conversion
result = result.Div(shardFactor)
_ = result.BigInt()
}
}