You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have identified an issue where zap.Any can cause performance
degradation due to stack size.
This is apparently cased by the compiler assigning 4.8kb (a zap.Field
per arm of the switch statement) for zap.Any on stack. This can result
in an unnecessary runtime.newstack+runtime.copystack.
A github issue against Go language is pending.
This can be particularly bad if `zap.Any` was to be used in a new
goroutine, since the default goroutine sizes can be as low as 2kb (it can
vary depending on average stack size - see golang/go#18138).
This is an alternative to #1301, @cdvr and me were talking about this,
and he inspired this idea with the closure.
By using a function and a closure we're able to reduce the size and
remove the degradation.
At least on my laptop, this change result in a new performance gain,
as all benchmarks show reduced time.
10 runs.
```
❯ benchstat ~/before.txt ~/after-after.txt
goos: darwin
goarch: arm64
pkg: go.uber.org/zap
│ /Users/pawel/before.txt │ /Users/pawel/after-after.txt │
│ sec/op │ sec/op vs base │
AnyInGoroutine/any-12 305.2n ± 3% 297.0n ± 0% ~ (p=0.085 n=10)
AnyInGoroutine/int-12 288.0n ± 0% 270.1n ± 1% -6.25% (p=0.000 n=10)
AnyInGoroutine/goroutine-12 218.3n ± 6% 209.5n ± 5% -4.05% (p=0.015 n=10)
AnyInGoroutine/int-in-go-12 592.7n ± 2% 573.9n ± 2% -3.17% (p=0.000 n=10)
AnyInGoroutine/any-in-go-12 666.5n ± 4% 552.3n ± 1% -17.13% (p=0.000 n=10)
AnyInGoroutine/int-in-go-with-stack-12 474.4n ± 4% 459.4n ± 6% ~ (p=0.447 n=10+9)
AnyInGoroutine/any-in-go-with-stack-12 617.6n ± 4% 468.8n ± 4% -24.09% (p=0.000 n=10)
geomean 417.8n 380.1n -9.01%
│ /Users/pawel/before.txt │ /Users/pawel/after-after.txt │
│ B/op │ B/op vs base │
AnyInGoroutine/any-12 64.00 ± 0% 64.00 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/int-12 64.00 ± 0% 64.00 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/goroutine-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/int-in-go-12 88.00 ± 0% 88.00 ± 0% ~ (p=1.000 n=10)
AnyInGoroutine/any-in-go-12 88.00 ± 0% 88.00 ± 0% ~ (p=1.000 n=10)
AnyInGoroutine/int-in-go-with-stack-12 88.00 ± 0% 88.00 ± 0% ~ (p=1.000 n=10+9) ¹
AnyInGoroutine/any-in-go-with-stack-12 88.00 ± 0% 88.00 ± 0% ~ (p=1.000 n=10) ¹
geomean ² +0.00% ²
¹ all samples are equal
² summaries must be >0 to compute geomean
│ /Users/pawel/before.txt │ /Users/pawel/after-after.txt │
│ allocs/op │ allocs/op vs base │
AnyInGoroutine/any-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/int-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/goroutine-12 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/int-in-go-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/any-in-go-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹
AnyInGoroutine/int-in-go-with-stack-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10+9) ¹
AnyInGoroutine/any-in-go-with-stack-12 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹
geomean ² +0.00% ²
¹ all samples are equal
² summaries must be >0 to compute geomean
```
0 commit comments