You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailscale/util
Joe Tsai 31bf3874d6
util/deephash: use unsafe.Pointer instead of reflect.Value (#5459)
Use of reflect.Value.SetXXX panics if the provided argument was
obtained from an unexported struct field.
Instead, pass an unsafe.Pointer around and convert to a
reflect.Value when necessary (i.e., for maps and interfaces).
Converting from unsafe.Pointer to reflect.Value guarantees that
none of the read-only bits will be populated.

When running in race mode, we attach type information to the pointer
so that we can type check every pointer operation.
This also type-checks that direct memory hashing is within
the valid range of a struct value.

We add test cases that previously caused deephash to panic,
but now pass.

Performance:

	name              old time/op    new time/op    delta
	Hash              14.1µs ± 1%    14.1µs ± 1%    ~     (p=0.590 n=10+9)
	HashPacketFilter  2.53µs ± 2%    2.44µs ± 1%  -3.79%  (p=0.000 n=9+10)
	TailcfgNode       1.45µs ± 1%    1.43µs ± 0%  -1.36%  (p=0.000 n=9+9)
	HashArray         318ns ± 2%     318ns ± 2%    ~      (p=0.541 n=10+10)
	HashMapAcyclic    32.9µs ± 1%    31.6µs ± 1%  -4.16%  (p=0.000 n=10+9)

There is a slight performance gain due to the use of unsafe.Pointer
over reflect.Value methods. Also, passing an unsafe.Pointer (1 word)
on the stack is cheaper than passing a reflect.Value (3 words).

Performance gains are diminishing since SHA-256 hashing now dominates the runtime.

Signed-off-by: Joe Tsai <joetsai@digital-static.net>
2 years ago
..
cibuild all: use cibuild.On 2 years ago
clientmetric all: gofmt for Go 1.19 2 years ago
cloudenv all: use syncs.AtomicValue 2 years ago
cmpver util/cmpver: move into OSS from corp repo. 3 years ago
codegen all: convert more code to use net/netip directly 2 years ago
deephash util/deephash: use unsafe.Pointer instead of reflect.Value (#5459) 2 years ago
dnsname all: use Go 1.18's strings.Cut 2 years ago
endian all: gofmt with Go 1.17 3 years ago
groupmember util/groupmember: remove redundant code (#4298) 2 years ago
hashx util/hashx: move from sha256x (#5388) 2 years ago
jsonutil all: use any instead of interface{} 2 years ago
lineread util/lineread: add docs to Reader 4 years ago
mak util/mak: move tailssh's mapSet into a new package for reuse elsewhere 2 years ago
multierr all: gofmt for Go 1.19 2 years ago
must util/must: rename Do->Get, add Do 2 years ago
osshare all: gofmt with Go 1.17 3 years ago
pidowner all: gofmt with Go 1.17 3 years ago
precompress cmd/tsconnect,util/precompress: move precompression to its own package 2 years ago
racebuild all: gofmt with Go 1.17 3 years ago
singleflight all: gofmt for Go 1.19 2 years ago
strs util/strs: add new package for string utility funcs 2 years ago
systemd all: gofmt for Go 1.19 2 years ago
uniq all: use any instead of interface{} 2 years ago
winutil util/winutil: consolidate interface specific registry keys 2 years ago