Skip to content

Commit 55dcbc7

Browse files
perf(nns): Change from benchmarking listing neurons for unstake maturity to benchmarking the entire unstake maturity operation (#4183)
# Why When trying to unstake maturity, not only the listing steps are computationally intensive, the actual unstaking is too, because it calls `with_neuron_mut` in a loop. We should cap the number of neurons to unstake in a single message, and this benchmark prepares for the improvement. # What * Refactor the `Governance::unstake_maturity_of_dissolved_neurons` to `NeuronStore::unstake_maturity_of_dissolved_neurons` since only neuron store is involved for this operation. * Change benchmark from `list_neurons_ready_to_unstake_maturity` to `unstake_maturity_of_dissolved_neurons` * Add bench scopes for listing and unstaking, since the former is linear to # of neurons and the latter depends on the available number of neurons to unstake maturity (and those 2 numbers don't have a reasonable ratio that we can assume) * Update bench results
1 parent 38618cf commit 55dcbc7

File tree

5 files changed

+79
-49
lines changed

5 files changed

+79
-49
lines changed

rs/nns/governance/canbench/canbench_results.yml

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,6 @@ benches:
101101
heap_increase: 9
102102
stable_memory_increase: 0
103103
scopes: {}
104-
list_neurons_ready_to_unstake_maturity_heap:
105-
total:
106-
instructions: 158195
107-
heap_increase: 0
108-
stable_memory_increase: 0
109-
scopes: {}
110-
list_neurons_ready_to_unstake_maturity_stable:
111-
total:
112-
instructions: 43332558
113-
heap_increase: 0
114-
stable_memory_increase: 0
115-
scopes: {}
116104
list_neurons_stable:
117105
total:
118106
instructions: 113665560
@@ -173,10 +161,38 @@ benches:
173161
heap_increase: 0
174162
stable_memory_increase: 128
175163
scopes: {}
164+
unstake_maturity_of_dissolved_neurons_heap:
165+
total:
166+
instructions: 2644396
167+
heap_increase: 0
168+
stable_memory_increase: 0
169+
scopes:
170+
list_neuron_ids:
171+
instructions: 225923
172+
heap_increase: 0
173+
stable_memory_increase: 0
174+
unstake_maturity:
175+
instructions: 2416625
176+
heap_increase: 0
177+
stable_memory_increase: 0
178+
unstake_maturity_of_dissolved_neurons_stable:
179+
total:
180+
instructions: 92282613
181+
heap_increase: 0
182+
stable_memory_increase: 0
183+
scopes:
184+
list_neuron_ids:
185+
instructions: 44812672
186+
heap_increase: 0
187+
stable_memory_increase: 0
188+
unstake_maturity:
189+
instructions: 47468213
190+
heap_increase: 0
191+
stable_memory_increase: 0
176192
update_recent_ballots_stable_memory:
177193
total:
178194
instructions: 275035
179195
heap_increase: 0
180196
stable_memory_increase: 0
181197
scopes: {}
182-
version: 0.1.8
198+
version: 0.1.9

rs/nns/governance/src/governance.rs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6562,30 +6562,11 @@ impl Governance {
65626562
xdr_permyriad_per_icp / dec!(10_000)
65636563
}
65646564

6565-
/// When a neuron is finally dissolved, if there is any staked maturity it is moved to regular maturity
6566-
/// which can be spawned (and is modulated).
6565+
/// Unstakes the maturity of neurons that have dissolved.
65676566
pub fn unstake_maturity_of_dissolved_neurons(&mut self) {
65686567
let now_seconds = self.env.now();
6569-
// Filter all the neurons that are currently in "dissolved" state and have some staked maturity.
6570-
// No neuron in stable storage should have staked maturity.
6571-
for neuron_id in self
6572-
.neuron_store
6573-
.list_neurons_ready_to_unstake_maturity(now_seconds)
6574-
{
6575-
let unstake_result = self
6576-
.neuron_store
6577-
.with_neuron_mut(&neuron_id, |neuron| neuron.unstake_maturity(now_seconds));
6578-
6579-
match unstake_result {
6580-
Ok(_) => {}
6581-
Err(e) => {
6582-
println!(
6583-
"{}Error in heartbeat when moving staked maturity for neuron {:?}: {:?}",
6584-
LOG_PREFIX, neuron_id, e
6585-
);
6586-
}
6587-
};
6588-
}
6568+
self.neuron_store
6569+
.unstake_maturity_of_dissolved_neurons(now_seconds);
65896570
}
65906571

65916572
fn can_spawn_neurons(&self) -> bool {

rs/nns/governance/src/neuron/types.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ pub struct NeuronBuilder {
17061706
recent_ballots_next_entry_index: Option<usize>,
17071707
#[cfg(test)]
17081708
transfer: Option<NeuronStakeTransfer>,
1709-
#[cfg(test)]
1709+
#[cfg(any(test, feature = "canbench-rs"))]
17101710
staked_maturity_e8s_equivalent: Option<u64>,
17111711
#[cfg(test)]
17121712
known_neuron_data: Option<KnownNeuronData>,
@@ -1748,7 +1748,7 @@ impl NeuronBuilder {
17481748
recent_ballots_next_entry_index: Some(0),
17491749
#[cfg(test)]
17501750
transfer: None,
1751-
#[cfg(test)]
1751+
#[cfg(any(test, feature = "canbench-rs"))]
17521752
staked_maturity_e8s_equivalent: None,
17531753
#[cfg(test)]
17541754
known_neuron_data: None,
@@ -1850,7 +1850,7 @@ impl NeuronBuilder {
18501850
self
18511851
}
18521852

1853-
#[cfg(test)]
1853+
#[cfg(any(test, feature = "canbench-rs"))]
18541854
pub fn with_staked_maturity_e8s_equivalent(
18551855
mut self,
18561856
staked_maturity_e8s_equivalent: u64,
@@ -1906,7 +1906,7 @@ impl NeuronBuilder {
19061906
recent_ballots_next_entry_index,
19071907
#[cfg(test)]
19081908
transfer,
1909-
#[cfg(test)]
1909+
#[cfg(any(test, feature = "canbench-rs"))]
19101910
staked_maturity_e8s_equivalent,
19111911
#[cfg(test)]
19121912
known_neuron_data,
@@ -1937,7 +1937,7 @@ impl NeuronBuilder {
19371937
let recent_ballots_next_entry_index = Some(0);
19381938
#[cfg(not(test))]
19391939
let transfer = None;
1940-
#[cfg(not(test))]
1940+
#[cfg(not(any(test, feature = "canbench-rs")))]
19411941
let staked_maturity_e8s_equivalent = None;
19421942
#[cfg(not(test))]
19431943
let known_neuron_data = None;

rs/nns/governance/src/neuron_store.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ impl NeuronStore {
907907
}
908908

909909
/// List all neuron ids whose neurons have staked maturity greater than 0.
910-
pub fn list_neurons_ready_to_unstake_maturity(&self, now_seconds: u64) -> Vec<NeuronId> {
910+
fn list_neurons_ready_to_unstake_maturity(&self, now_seconds: u64) -> Vec<NeuronId> {
911911
self.with_active_neurons_iter_sections(
912912
|iter| {
913913
iter.filter(|neuron| neuron.ready_to_unstake_maturity(now_seconds))
@@ -981,6 +981,35 @@ impl NeuronStore {
981981
(ballots, deciding_voting_power, potential_voting_power)
982982
}
983983

984+
/// When a neuron is finally dissolved, if there is any staked maturity it is moved to regular maturity
985+
/// which can be spawned (and is modulated).
986+
pub fn unstake_maturity_of_dissolved_neurons(&mut self, now_seconds: u64) {
987+
let neuron_ids = {
988+
#[cfg(feature = "canbench-rs")]
989+
let _scope_list = canbench_rs::bench_scope("list_neuron_ids");
990+
self.list_neurons_ready_to_unstake_maturity(now_seconds)
991+
};
992+
993+
#[cfg(feature = "canbench-rs")]
994+
let _scope_unstake = canbench_rs::bench_scope("unstake_maturity");
995+
// Filter all the neurons that are currently in "dissolved" state and have some staked maturity.
996+
// No neuron in stable storage should have staked maturity.
997+
for neuron_id in neuron_ids {
998+
let unstake_result =
999+
self.with_neuron_mut(&neuron_id, |neuron| neuron.unstake_maturity(now_seconds));
1000+
1001+
match unstake_result {
1002+
Ok(_) => {}
1003+
Err(e) => {
1004+
println!(
1005+
"{}Error when moving staked maturity for neuron {:?}: {:?}",
1006+
LOG_PREFIX, neuron_id, e
1007+
);
1008+
}
1009+
};
1010+
}
1011+
}
1012+
9841013
/// Returns the full neuron if the given principal is authorized - either it can vote for the
9851014
/// given neuron or any of its neuron managers.
9861015
pub fn get_full_neuron(

rs/nns/governance/src/neuron_store/benches.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ fn add_neuron_ready_to_unstake_maturity(
318318
) {
319319
let id = rng.next_u64();
320320
let subaccount = subaccount_from_id(id);
321-
let mut neuron = NeuronBuilder::new(
321+
let neuron = NeuronBuilder::new(
322322
NeuronId { id: rng.next_u64() },
323323
subaccount,
324324
PrincipalId::new_user_test_id(id),
@@ -327,32 +327,36 @@ fn add_neuron_ready_to_unstake_maturity(
327327
},
328328
123_456_789,
329329
)
330+
.with_staked_maturity_e8s_equivalent(1_000_000_000)
330331
.build();
331-
neuron.staked_maturity_e8s_equivalent = Some(1_000_000_000);
332332
neuron_store.add_neuron(neuron).unwrap();
333333
}
334334

335335
#[bench(raw)]
336-
fn list_neurons_ready_to_unstake_maturity_heap() -> BenchResult {
336+
fn unstake_maturity_of_dissolved_neurons_heap() -> BenchResult {
337337
let _a = temporarily_disable_allow_active_neurons_in_stable_memory();
338338
let _b = temporarily_disable_migrate_active_neurons_to_stable_memory();
339339
let mut rng = new_rng();
340340
let mut neuron_store = set_up_neuron_store(&mut rng, 1_000, 2_000);
341-
add_neuron_ready_to_unstake_maturity(now_seconds(), &mut rng, &mut neuron_store);
341+
for _ in 0..100 {
342+
add_neuron_ready_to_unstake_maturity(now_seconds(), &mut rng, &mut neuron_store);
343+
}
342344

343-
bench_fn(|| neuron_store.list_neurons_ready_to_unstake_maturity(now_seconds()))
345+
bench_fn(|| neuron_store.unstake_maturity_of_dissolved_neurons(now_seconds()))
344346
}
345347

346348
#[bench(raw)]
347-
fn list_neurons_ready_to_unstake_maturity_stable() -> BenchResult {
349+
fn unstake_maturity_of_dissolved_neurons_stable() -> BenchResult {
348350
let _a = temporarily_enable_allow_active_neurons_in_stable_memory();
349351
let _b = temporarily_enable_migrate_active_neurons_to_stable_memory();
350352
let mut rng = new_rng();
351353
let mut neuron_store = set_up_neuron_store(&mut rng, 1_000, 2_000);
352-
add_neuron_ready_to_unstake_maturity(now_seconds(), &mut rng, &mut neuron_store);
354+
for _ in 0..100 {
355+
add_neuron_ready_to_unstake_maturity(now_seconds(), &mut rng, &mut neuron_store);
356+
}
353357

354358
bench_fn(|| {
355-
neuron_store.list_neurons_ready_to_unstake_maturity(now_seconds());
359+
neuron_store.unstake_maturity_of_dissolved_neurons(now_seconds());
356360
})
357361
}
358362

0 commit comments

Comments
 (0)