]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: avoid stack copies of hiter
authorMartin Möhrmann <martin@golang.org>
Sun, 31 Oct 2021 16:58:07 +0000 (17:58 +0100)
committerMartin Möhrmann <martin@golang.org>
Sun, 31 Oct 2021 18:39:05 +0000 (18:39 +0000)
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 <josharian@gmail.com>
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Martin Möhrmann <martin@golang.org>

src/reflect/all_test.go
src/reflect/value.go

index 725be28bf01bf55c5c43cef257a06c5db6fd3465..acc09962a0bc933c14cf9b05924b7e36cd4d41db 100644 (file)
@@ -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}
index 90edf8e31ddf6d76ee2b48ce6e395a58462f35c4..ecf9dd7bc86fb933b2bfb718d32d5f50a79e0c21 100644 (file)
@@ -1665,7 +1665,7 @@ type hiter struct {
        checkBucket uintptr
 }
 
-func (h hiter) initialized() bool {
+func (h *hiter) initialized() bool {
        return h.t != nil
 }