github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/validators/manager_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 validators 5 6 import ( 7 "context" 8 "math/rand" 9 "testing" 10 "time" 11 12 "github.com/prometheus/client_golang/prometheus" 13 "github.com/stretchr/testify/require" 14 15 "github.com/ava-labs/avalanchego/database/leveldb" 16 "github.com/ava-labs/avalanchego/ids" 17 "github.com/ava-labs/avalanchego/snow/validators" 18 "github.com/ava-labs/avalanchego/utils/constants" 19 "github.com/ava-labs/avalanchego/utils/crypto/bls" 20 "github.com/ava-labs/avalanchego/utils/logging" 21 "github.com/ava-labs/avalanchego/utils/timer/mockable" 22 "github.com/ava-labs/avalanchego/utils/units" 23 "github.com/ava-labs/avalanchego/vms/platformvm/block" 24 "github.com/ava-labs/avalanchego/vms/platformvm/config" 25 "github.com/ava-labs/avalanchego/vms/platformvm/genesis/genesistest" 26 "github.com/ava-labs/avalanchego/vms/platformvm/metrics" 27 "github.com/ava-labs/avalanchego/vms/platformvm/state" 28 "github.com/ava-labs/avalanchego/vms/platformvm/state/statetest" 29 "github.com/ava-labs/avalanchego/vms/platformvm/txs" 30 ) 31 32 // BenchmarkGetValidatorSet generates 10k diffs and calculates the time to 33 // generate the genesis validator set by applying them. 34 // 35 // This generates a single diff for each height. In practice there could be 36 // multiple or zero diffs at a given height. 37 // 38 // Note: BenchmarkGetValidatorSet gets the validator set of a subnet rather than 39 // the primary network because the primary network performs caching that would 40 // interfere with the benchmark. 41 func BenchmarkGetValidatorSet(b *testing.B) { 42 require := require.New(b) 43 44 db, err := leveldb.New( 45 b.TempDir(), 46 nil, 47 logging.NoLog{}, 48 prometheus.NewRegistry(), 49 ) 50 require.NoError(err) 51 defer func() { 52 require.NoError(db.Close()) 53 }() 54 55 vdrs := validators.NewManager() 56 s := statetest.New(b, statetest.Config{ 57 DB: db, 58 Validators: vdrs, 59 }) 60 61 m := NewManager( 62 logging.NoLog{}, 63 config.Config{ 64 Validators: vdrs, 65 }, 66 s, 67 metrics.Noop, 68 new(mockable.Clock), 69 ) 70 71 var ( 72 nodeIDs []ids.NodeID 73 currentHeight uint64 74 ) 75 for i := 0; i < 50; i++ { 76 currentHeight++ 77 nodeID, err := addPrimaryValidator(s, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, currentHeight) 78 require.NoError(err) 79 nodeIDs = append(nodeIDs, nodeID) 80 } 81 subnetID := ids.GenerateTestID() 82 for _, nodeID := range nodeIDs { 83 currentHeight++ 84 require.NoError(addSubnetValidator(s, subnetID, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, nodeID, currentHeight)) 85 } 86 for i := 0; i < 9900; i++ { 87 currentHeight++ 88 require.NoError(addSubnetDelegator(s, subnetID, genesistest.DefaultValidatorStartTime, genesistest.DefaultValidatorEndTime, nodeIDs, currentHeight)) 89 } 90 91 ctx := context.Background() 92 height, err := m.GetCurrentHeight(ctx) 93 require.NoError(err) 94 require.Equal(currentHeight, height) 95 96 b.ResetTimer() 97 98 for i := 0; i < b.N; i++ { 99 _, err := m.GetValidatorSet(ctx, 0, subnetID) 100 require.NoError(err) 101 } 102 103 b.StopTimer() 104 } 105 106 func addPrimaryValidator( 107 s state.State, 108 startTime time.Time, 109 endTime time.Time, 110 height uint64, 111 ) (ids.NodeID, error) { 112 sk, err := bls.NewSecretKey() 113 if err != nil { 114 return ids.EmptyNodeID, err 115 } 116 117 nodeID := ids.GenerateTestNodeID() 118 if err := s.PutCurrentValidator(&state.Staker{ 119 TxID: ids.GenerateTestID(), 120 NodeID: nodeID, 121 PublicKey: bls.PublicFromSecretKey(sk), 122 SubnetID: constants.PrimaryNetworkID, 123 Weight: 2 * units.MegaAvax, 124 StartTime: startTime, 125 EndTime: endTime, 126 PotentialReward: 0, 127 NextTime: endTime, 128 Priority: txs.PrimaryNetworkValidatorCurrentPriority, 129 }); err != nil { 130 return ids.EmptyNodeID, err 131 } 132 133 blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil) 134 if err != nil { 135 return ids.EmptyNodeID, err 136 } 137 138 s.AddStatelessBlock(blk) 139 s.SetHeight(height) 140 return nodeID, s.Commit() 141 } 142 143 func addSubnetValidator( 144 s state.State, 145 subnetID ids.ID, 146 startTime time.Time, 147 endTime time.Time, 148 nodeID ids.NodeID, 149 height uint64, 150 ) error { 151 if err := s.PutCurrentValidator(&state.Staker{ 152 TxID: ids.GenerateTestID(), 153 NodeID: nodeID, 154 SubnetID: subnetID, 155 Weight: 1 * units.Avax, 156 StartTime: startTime, 157 EndTime: endTime, 158 PotentialReward: 0, 159 NextTime: endTime, 160 Priority: txs.SubnetPermissionlessValidatorCurrentPriority, 161 }); err != nil { 162 return err 163 } 164 165 blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil) 166 if err != nil { 167 return err 168 } 169 170 s.AddStatelessBlock(blk) 171 s.SetHeight(height) 172 return s.Commit() 173 } 174 175 func addSubnetDelegator( 176 s state.State, 177 subnetID ids.ID, 178 startTime time.Time, 179 endTime time.Time, 180 nodeIDs []ids.NodeID, 181 height uint64, 182 ) error { 183 i := rand.Intn(len(nodeIDs)) //#nosec G404 184 nodeID := nodeIDs[i] 185 s.PutCurrentDelegator(&state.Staker{ 186 TxID: ids.GenerateTestID(), 187 NodeID: nodeID, 188 SubnetID: subnetID, 189 Weight: 1 * units.Avax, 190 StartTime: startTime, 191 EndTime: endTime, 192 PotentialReward: 0, 193 NextTime: endTime, 194 Priority: txs.SubnetPermissionlessDelegatorCurrentPriority, 195 }) 196 197 blk, err := block.NewBanffStandardBlock(startTime, ids.GenerateTestID(), height, nil) 198 if err != nil { 199 return err 200 } 201 202 s.AddStatelessBlock(blk) 203 s.SetLastAccepted(blk.ID()) 204 s.SetHeight(height) 205 return s.Commit() 206 }