diff --git a/prdoc/pr_10802.prdoc b/prdoc/pr_10802.prdoc new file mode 100644 index 0000000000000..1e79b476a404e --- /dev/null +++ b/prdoc/pr_10802.prdoc @@ -0,0 +1,13 @@ +title: 'benchmarking: fix timing leak from bulk setup operations' +doc: +- audience: Runtime Dev + description: |- + Fixes timing leaks in benchmarks with large setup operations (e.g., clearing + 27k staking entries). After bulk deletions are committed, the first new allocation + can trigger memory allocator overhead that leaks into benchmark timing. + + The fix adds a memory allocator warmup step in `commit_db()` that performs a + dummy write/clear cycle to absorb this overhead before timing starts. +crates: +- name: frame-benchmarking + bump: patch diff --git a/substrate/frame/benchmarking/src/utils.rs b/substrate/frame/benchmarking/src/utils.rs index 0f0cc3558a1ff..c41c6a99854cd 100644 --- a/substrate/frame/benchmarking/src/utils.rs +++ b/substrate/frame/benchmarking/src/utils.rs @@ -289,7 +289,17 @@ pub trait Benchmarking { /// Commit pending storage changes to the trie database and clear the database cache. fn commit_db(&mut self) { - self.commit() + self.commit(); + + // Warmup the memory allocator after bulk deallocation. + // After draining the overlay with many entries, the first new allocation can trigger memory + // defragmentation. + const WARMUP_KEY: &[u8] = b":benchmark_warmup:"; + self.place_storage(WARMUP_KEY.to_vec(), Some(vec![0u8; 32])); + self.place_storage(WARMUP_KEY.to_vec(), None); + + // Reset tracking so warmup operations don't appear in benchmark results. + self.reset_read_write_count(); } /// Get the read/write count.