From: Martin Möhrmann Date: Sun, 31 Oct 2021 16:58:07 +0000 (+0100) Subject: reflect: avoid stack copies of hiter X-Git-Tag: go1.18beta1~651 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=89c527007f75884a78ffede5d493ec021e7dfcdc;p=gostls13.git reflect: avoid stack copies of hiter 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 --- 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 }