From 9fd2e4443955127ed360338cb19a5aeba6be1a8c Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 13 Nov 2025 17:17:35 +0000 Subject: [PATCH] runtime: add AddCleanup benchmark Change-Id: Ia463a9b3b5980670bcf9297b4bddb60980ebfde5 Reviewed-on: https://go-review.googlesource.com/c/go/+/720320 Auto-Submit: Michael Knyszek Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee --- src/runtime/mcleanup_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/runtime/mcleanup_test.go b/src/runtime/mcleanup_test.go index 22b9eccd20..341d30afa7 100644 --- a/src/runtime/mcleanup_test.go +++ b/src/runtime/mcleanup_test.go @@ -336,3 +336,31 @@ func TestCleanupLost(t *testing.T) { t.Errorf("expected %d cleanups to be executed, got %d", got, want) } } + +// BenchmarkAddCleanupAndStop benchmarks adding and removing a cleanup +// from the same allocation. +// +// At face value, this benchmark is unrealistic, since no program would +// do this in practice. However, adding cleanups to new allocations in a +// loop is also unrealistic. It adds additional unused allocations, +// exercises uncommon performance pitfalls in AddCleanup (traversing the +// specials list, which should just be its own benchmark), and executing +// cleanups at a frequency that is unlikely to appear in real programs. +// +// This benchmark is still useful however, since we can get a low-noise +// measurement of the cost of AddCleanup and Stop all in one without the +// above pitfalls: we can measure the pure overhead. We can then separate +// out the cost of each in CPU profiles if we so choose (they're not so +// inexpensive as to make this infeasible). +func BenchmarkAddCleanupAndStop(b *testing.B) { + b.ReportAllocs() + + type T struct { + v int + p unsafe.Pointer + } + x := new(T) + for b.Loop() { + runtime.AddCleanup(x, func(int) {}, 14).Stop() + } +} -- 2.52.0