From 89c527007f75884a78ffede5d493ec021e7dfcdc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20M=C3=B6hrmann?= Date: Sun, 31 Oct 2021 17:58:07 +0100 Subject: [PATCH] reflect: avoid stack copies of hiter MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use a pointer reciever to avoid copying the hiter struct when checking if it is intialized. Found through profiling that showed reflect map iteration spending a good amount of time in duffcopy. This change will also help other MapIter methods checking hiter struct initialization like Value() and Key(). name old time/op new time/op delta MapIterNext-12 97.9ns ± 4% 83.8ns ± 2% -14.37% (p=0.000 n=10+10) Change-Id: I73ab964fa28061ee7e6d5c663a85048bd2e0274e Reviewed-on: https://go-review.googlesource.com/c/go/+/360254 Reviewed-by: Josh Bleecher Snyder Trust: Josh Bleecher Snyder Trust: Martin Möhrmann --- src/reflect/all_test.go | 10 ++++++++++ src/reflect/value.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 725be28bf0..acc09962a0 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7568,6 +7568,16 @@ func TestMapIterNext(t *testing.T) { } } +func BenchmarkMapIterNext(b *testing.B) { + m := ValueOf(map[string]int{"a": 0, "b": 1, "c": 2, "d": 3}) + it := m.MapRange() + for i := 0; i < b.N; i++ { + for it.Next() { + } + it.Reset(m) + } +} + func TestMapIterDelete0(t *testing.T) { // Delete all elements before first iteration. m := map[string]int{"one": 1, "two": 2, "three": 3} diff --git a/src/reflect/value.go b/src/reflect/value.go index 90edf8e31d..ecf9dd7bc8 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1665,7 +1665,7 @@ type hiter struct { checkBucket uintptr } -func (h hiter) initialized() bool { +func (h *hiter) initialized() bool { return h.t != nil } -- 2.50.0