The Go programming language https://go.dev
Find a file
thepudds a8e0641d5b reflect: optimize IsZero with a pointer comparison to global zeroVal
Our prior CL 649078 teaches the compiler to use a pointer to
runtime.zeroVal as the data pointer for an interface in cases it where
it can see that a zero value struct or array is being used in
an interface conversion.

This applies to some uses with reflect, such as:

  s := S{}
  v := reflect.ValueOf(s)

This CL builds on that to do a cheap pointer check in reflect.IsZero
to see if the Value points to runtime.zeroVal, which means it is a zero
value.

An alternative might be to do an initial pointer check in the typ.Equal
function for types where it makes sense to do but doesn't already.

This CL gives a performance boost of -51.71% geomean for
BenchmarkZero/IsZero, with most of the impact there on
arrays of structs. (The left column is CL 649078 and the right column
is this CL).

goos: linux
goarch: amd64
pkg: reflect
cpu: Intel(R) Xeon(R) CPU @ 2.80GHz
                                         │ find-zeroVal │          check-zeroVal              │
                                         │    sec/op    │   sec/op     vs base                │
Zero/IsZero/ByteArray/size=16-4             4.171n ± 0%   3.123n ± 0%  -25.13% (p=0.000 n=20)
Zero/IsZero/ByteArray/size=64-4             3.864n ± 0%   3.129n ± 0%  -19.02% (p=0.000 n=20)
Zero/IsZero/ByteArray/size=1024-4           3.878n ± 0%   3.126n ± 0%  -19.39% (p=0.000 n=20)
Zero/IsZero/BigStruct/size=1024-4           5.061n ± 0%   3.273n ± 0%  -35.34% (p=0.000 n=20)
Zero/IsZero/SmallStruct/size=16-4           4.191n ± 0%   3.275n ± 0%  -21.87% (p=0.000 n=20)
Zero/IsZero/SmallStructArray/size=64-4      8.636n ± 0%   3.127n ± 0%  -63.79% (p=0.000 n=20)
Zero/IsZero/SmallStructArray/size=1024-4   80.055n ± 0%   3.126n ± 0%  -96.10% (p=0.000 n=20)
Zero/IsZero/Time/size=24-4                  3.865n ± 0%   3.274n ± 0%  -15.29% (p=0.000 n=20)
geomean                                     6.587n        3.181n       -51.71%

Note these are of course micro benchmarks with easily predicted
branches. The extra branch we introduce in the CL might hurt if there
was for example a tight loop where 50% of the values used the
global zeroVal and 50% didn't in a way that is not well predicted,
although if the typ.Equal for many types already does an initial
pointer check, it might not matter much.

For the older BenchmarkIsZero in reflect, this change does not help.
(The compiler does not use the global zeroVal as the data word for the
interfaces in this benchmark because values are part of a larger value
that is too big to be used in the global zeroVal, and also a piece of
the larger value is mutated and is not zero).

                              │ find-zeroVal │           check-zeroVal            │
                              │   sec/op     │   sec/op     vs base               │
IsZero/ArrayComparable-4        14.58n ± 0%    14.59n ± 0%       ~ (p=0.177 n=20)
IsZero/ArrayIncomparable-4      163.8n ± 0%    167.5n ± 0%  +2.26% (p=0.000 n=20)
IsZero/StructComparable-4       6.847n ± 0%    6.847n ± 0%       ~ (p=0.703 n=20)
IsZero/StructIncomparable-4     35.41n ± 0%    35.10n ± 0%  -0.86% (p=0.000 n=20)
IsZero/ArrayInt_4-4             8.631n ± 0%    8.363n ± 0%  -3.10% (p=0.000 n=20)
IsZero/ArrayInt_1024-4          265.5n ± 0%    265.4n ± 0%       ~ (p=0.288 n=20)
IsZero/ArrayInt_1024_NoZero-4   135.8n ± 0%    136.2n ± 0%  +0.33% (p=0.000 n=20)
IsZero/Struct4Int-4             8.451n ± 0%    8.386n ± 0%  -0.77% (p=0.000 n=20)
IsZero/ArrayStruct4Int_1024-4   265.2n ± 0%    266.0n ± 0%  +0.30% (p=0.000 n=20)
IsZero/ArrayChanInt_1024-4      265.5n ± 0%    265.4n ± 0%       ~ (p=0.605 n=20)
IsZero/StructInt_512-4          135.8n ± 0%    135.8n ± 0%       ~ (p=0.396 n=20)
geomean                         55.22n         55.12n       -0.18%

Updates #71323

Change-Id: Ie083853a5bff03856277a293d94532a681f4a8d5
Reviewed-on: https://go-review.googlesource.com/c/go/+/654135
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-05-21 12:25:04 -07:00
.github .github: update language change proposal template 2024-08-08 19:02:29 +00:00
api crypto/tls: add GetEncryptedClientHelloKeys 2025-05-21 12:15:37 -07:00
doc crypto/tls: have servers prefer TLS 1.3 when supported 2025-05-21 12:17:01 -07:00
lib lib/fips140: set inprocess.txt to v1.0.0 2025-05-21 10:59:42 -07:00
misc misc/linkcheck: remove unused tool 2025-03-20 04:38:55 -07:00
src reflect: optimize IsZero with a pointer comparison to global zeroVal 2025-05-21 12:25:04 -07:00
test cmd/compile/internal/walk: use global zeroVal in interface conversions for zero values 2025-05-21 12:24:22 -07:00
.gitattributes all: treat all files as binary, but check in .bat with CRLF 2020-06-08 15:31:43 +00:00
.gitignore runtime,internal: move runtime/internal/sys to internal/runtime/sys 2024-07-23 19:05:35 +00:00
codereview.cfg codereview.cfg: add codereview.cfg for master branch 2021-02-19 18:44:53 +00:00
CONTRIBUTING.md doc: normalize proposal-process links 2023-03-29 22:00:27 +00:00
go.env cmd/go: additional doc-inspired tests and bug fixes 2023-06-06 19:18:46 +00:00
LICENSE LICENSE: update per Google Legal 2024-08-09 14:54:31 +00:00
PATENTS LICENSE: separate, change PATENTS text 2010-12-06 16:31:59 -05:00
README.md README: fix CC BY license name 2024-07-22 17:45:27 +00:00
SECURITY.md SECURITY.md: update the Reporting a Vulnerability link 2023-09-22 21:17:24 +00:00

The Go Programming Language

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Gopher image Gopher image by Renee French, licensed under Creative Commons 4.0 Attribution license.

Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.

Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.

Download and Install

Binary Distributions

Official binary distributions are available at https://go.dev/dl/.

After downloading a binary release, visit https://go.dev/doc/install for installation instructions.

Install From Source

If a binary distribution is not available for your combination of operating system and architecture, visit https://go.dev/doc/install/source for source installation instructions.

Contributing

Go is the work of thousands of contributors. We appreciate your help!

To contribute, please read the contribution guidelines at https://go.dev/doc/contribute.

Note that the Go project uses the issue tracker for bug reports and proposals only. See https://go.dev/wiki/Questions for a list of places to ask questions about the Go language.