The reflect.Type.Elem method is somewhat slow,
which is unfortunate since the reflect.TypeOf((*T)(nil)).Elem()
trick is only needed if T is an interface.
Optimize for concrete types by doing the faster reflect.TypeOf(v)
call first and only falling back on the Elem method if needed.
Performance:
name old time/op new time/op delta
TypeForString-24 9.10ns ± 1% 1.78ns ± 2% -80.49% (p=0.000 n=10+10)
TypeForError-24 9.55ns ± 1% 9.78ns ± 1% +2.39% (p=0.000 n=10+9)
Updates #60088
Change-Id: I2ae76988c9a3dbcbae10d2c19b55db3c8d4559bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/555597
Auto-Submit: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Joseph Tsai <joetsai@digital-static.net>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
// TypeFor returns the [Type] that represents the type argument T.
func TypeFor[T any]() Type {
- return TypeOf((*T)(nil)).Elem()
+ var v T
+ if t := TypeOf(v); t != nil {
+ return t // optimize for T being a non-interface kind
+ }
+ return TypeOf((*T)(nil)).Elem() // only for an interface kind
}
})
}
}
+
+var sinkType reflect.Type
+
+func BenchmarkTypeForString(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkType = reflect.TypeFor[string]()
+ }
+}
+
+func BenchmarkTypeForError(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkType = reflect.TypeFor[error]()
+ }
+}