For programs with very large environments, calling unsetenv(3) for each
environment variable can be very expensive because of CGo overhead, but
clearenv(3) is much faster. The only thing we have to track is whether
GODEBUG is being unset by the operation, which can be done very quickly
without resorting to doing unsetenv(3) for every variable.
This change makes syscall.Clearenv() >98% faster when run in an
environment with as little as 100 environment variables. (Note that due
to golang/go#27217, it is necessary to modify BenchmarkClearenv to use
t.StopTimer() and -benchtime=100x in order to get these benchmark times
-- otherwise syscall.Setenv() time is included and the benchmarks give a
more pessimistic 50% performance improvement.)
goos: linux
goarch: amd64
pkg: syscall
cpu: AMD Ryzen 7 7840U w/ Radeon 780M Graphics
│ before │ after │
│ sec/op │ sec/op vs base │
Clearenv/100-16 22276.5n ± 5% 285.8n ± 3% -98.72% (p=0.000 n=10)
Clearenv/1000-16 1414104.0n ± 1% 783.1n ± 8% -99.94% (p=0.000 n=10)
Clearenv/10000-16 143827.554µ ± 1% 7.591µ ± 5% -99.99% (p=0.000 n=10)
geomean 1.655m 1.193µ -99.93%
The above benchmarks are CGo builds, which require CGo overhead for
every setenv(2). If you run the same benchmarks for a non-CGo package
(i.e., outside of the "syscall" package), you get slightly more modest
performance improvements:
goos: linux
goarch: amd64
pkg: clearenv_nocgo
cpu: AMD Ryzen 7 7840U w/ Radeon 780M Graphics
│ before │ after │
│ sec/op │ sec/op vs base │
Clearenv/100-16 1106.0n ± 3% 230.7n ± 8% -79.14% (p=0.000 n=10)
Clearenv/1000-16 11222.0n ± 1% 305.4n ± 6% -97.28% (p=0.000 n=10)
Clearenv/10000-16 195676.5n ± 6% 759.9n ± 10% -99.61% (p=0.000 n=10)
geomean 13.44µ 376.9n -97.20%
(As above, this requires modifying the benchmarks to use t.StopTimer()
and -benchtime=100x.)
Change-Id: I53b96a75f189e91affbde423c907888b7e0fafcd
GitHub-Last-Rev: f8d7a8140d
GitHub-Pull-Request: golang/go#70672
Reviewed-on: https://go-review.googlesource.com/c/go/+/633515
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>