aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/all_test.go
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2022-04-16 19:01:48 -0700
committerGopher Robot <gobot@golang.org>2022-04-21 23:45:36 +0000
commit67d6be139c77b63395d8c1fa29cdae8d34635f3e (patch)
tree446c84e256f30ff0c09325361e2ecb8e42fc65f6 /src/reflect/all_test.go
parent3c29aca43630da1604c3378d2351050f23655268 (diff)
downloadgo-67d6be139c77b63395d8c1fa29cdae8d34635f3e.tar.gz
go-67d6be139c77b63395d8c1fa29cdae8d34635f3e.zip
reflect: make more Value methods inlineable
The following Value methods are now inlineable: Bool for ~bool String for ~string (but not other kinds) Bytes for []byte (but not ~[]byte or ~[N]byte) Len for ~[]T (but not ~[N]T, ~chan T, ~map[K]V, or ~string) Cap for ~[]T (but not ~[N]T or ~chan T) For Bytes, we only have enough inline budget to inline one type, so we optimize for unnamed []byte, which is far more common than named []byte or [N]byte. For Len and Cap, we only have enough inline budget to inline one kind, so we optimize for ~[]T, which is more common than the others. The exception is string, but the size of a string can be obtained through len(v.String()). Performance: Bool 1.65ns ± 0% 0.51ns ± 3% -68.81% (p=0.008 n=5+5) String 1.97ns ± 1% 0.70ns ± 1% -64.25% (p=0.008 n=5+5) Bytes 8.90ns ± 2% 0.89ns ± 1% -89.95% (p=0.008 n=5+5) NamedBytes 8.89ns ± 1% 8.88ns ± 1% ~ (p=0.548 n=5+5) BytesArray 10.0ns ± 2% 10.2ns ± 1% +1.58% (p=0.048 n=5+5) SliceLen 1.97ns ± 1% 0.45ns ± 1% -77.22% (p=0.008 n=5+5) MapLen 2.62ns ± 1% 3.07ns ± 1% +17.24% (p=0.008 n=5+5) StringLen 1.96ns ± 1% 1.98ns ± 2% ~ (p=0.151 n=5+5) ArrayLen 1.96ns ± 1% 2.19ns ± 1% +11.46% (p=0.008 n=5+5) SliceCap 1.76ns ± 1% 0.45ns ± 2% -74.28% (p=0.008 n=5+5) There's a slight slowdown (~10-20%) for obtaining the length of a string or map, but a substantial improvement for slices. Performance according to encoding/json: CodeMarshal 555µs ± 2% 562µs ± 4% ~ (p=0.421 n=5+5) MarshalBytes/32 163ns ± 1% 157ns ± 1% -3.82% (p=0.008 n=5+5) MarshalBytes/256 453ns ± 1% 447ns ± 1% ~ (p=0.056 n=5+5) MarshalBytes/4096 4.10µs ± 1% 4.09µs ± 0% ~ (p=1.000 n=5+4) CodeUnmarshal 3.16ms ± 2% 3.02ms ± 1% -4.18% (p=0.008 n=5+5) CodeUnmarshalReuse 2.64ms ± 3% 2.51ms ± 2% -4.81% (p=0.016 n=5+5) UnmarshalString 65.4ns ± 4% 64.1ns ± 0% ~ (p=0.190 n=5+4) UnmarshalFloat64 59.8ns ± 5% 58.9ns ± 2% ~ (p=0.222 n=5+5) UnmarshalInt64 51.7ns ± 1% 50.0ns ± 2% -3.26% (p=0.008 n=5+5) EncodeMarshaler 23.6ns ±11% 20.8ns ± 1% -12.10% (p=0.016 n=5+4) Add all inlineable methods of Value to cmd/compile/internal/test/inl_test.go. Change-Id: Ifc192491918af6b62f7fe3a094a5a5256bfb326d Reviewed-on: https://go-review.googlesource.com/c/go/+/400676 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/reflect/all_test.go')
-rw-r--r--src/reflect/all_test.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index a886f9f64a..72d01c7deb 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -7823,3 +7823,93 @@ func TestNegativeKindString(t *testing.T) {
t.Fatalf("Kind(-1).String() = %q, want %q", s, want)
}
}
+
+type (
+ namedBool bool
+ namedBytes []byte
+)
+
+var sourceAll = struct {
+ Bool Value
+ String Value
+ Bytes Value
+ NamedBytes Value
+ BytesArray Value
+ SliceAny Value
+ MapStringAny Value
+}{
+ Bool: ValueOf(new(bool)).Elem(),
+ String: ValueOf(new(string)).Elem(),
+ Bytes: ValueOf(new([]byte)).Elem(),
+ NamedBytes: ValueOf(new(namedBytes)).Elem(),
+ BytesArray: ValueOf(new([32]byte)).Elem(),
+ SliceAny: ValueOf(new([]any)).Elem(),
+ MapStringAny: ValueOf(new(map[string]any)).Elem(),
+}
+
+var sinkAll struct {
+ RawBool bool
+ RawString string
+ RawBytes []byte
+ RawInt int
+}
+
+func BenchmarkBool(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawBool = sourceAll.Bool.Bool()
+ }
+}
+
+func BenchmarkString(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawString = sourceAll.String.String()
+ }
+}
+
+func BenchmarkBytes(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawBytes = sourceAll.Bytes.Bytes()
+ }
+}
+
+func BenchmarkNamedBytes(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawBytes = sourceAll.NamedBytes.Bytes()
+ }
+}
+
+func BenchmarkBytesArray(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawBytes = sourceAll.BytesArray.Bytes()
+ }
+}
+
+func BenchmarkSliceLen(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawInt = sourceAll.SliceAny.Len()
+ }
+}
+
+func BenchmarkMapLen(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawInt = sourceAll.MapStringAny.Len()
+ }
+}
+
+func BenchmarkStringLen(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawInt = sourceAll.String.Len()
+ }
+}
+
+func BenchmarkArrayLen(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawInt = sourceAll.BytesArray.Len()
+ }
+}
+
+func BenchmarkSliceCap(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkAll.RawInt = sourceAll.SliceAny.Cap()
+ }
+}