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
Using github.com/go-logr/logr, I ran a benchmark that shows an optimization that is missing. In fact, we wrote the code this way because Russ et al said this optimization could be done in future, so this is not so much a bug report as it is a feature request.
Here is the benchamark:
package main
import (
"testing""github.com/go-logr/logr"
)
//go:noinlinefuncdoV9(b*testing.B, log logr.Logger) {
b.ReportAllocs()
fori:=0; i<b.N; i++ {
log.V(9).Info("multi",
"bool", true, "string", "str", "int", 42,
"float", 3.14, "struct", struct{ X, Yint }{93, 76})
}
}
//go:noinlinefuncdoManualV9(b*testing.B, log logr.Logger) {
b.ReportAllocs()
fori:=0; i<b.N; i++ {
// This manual optimization should not be needed?iflogV:=log.V(9); logV.Enabled() {
logV.Info("multi",
"bool", true, "string", "str", "int", 42,
"float", 3.14, "struct", struct{ X, Yint }{93, 76})
}
}
}
// This is a simple repro all in one package.typeReprostruct {
enabledbool
}
//go:noinlinefunc (rRepro) Info(msgstring, keysAndValues...interface{}) {
// It looks like the slice allocation is elided?ifr.enabled {
r.Impl(msg, keysAndValues...)
}
}
//go:noinlinefunc (rRepro) Impl(_string, _...interface{}) {
panic("this should not get called")
}
//go:noinlinefuncdoLocalRepro(b*testing.B, reproRepro) {
b.ReportAllocs()
fori:=0; i<b.N; i++ {
repro.Info("multi",
"bool", true, "string", "str", "int", 42,
"float", 3.14, "struct", struct{ X, Yint }{93, 76})
}
}
funcBenchmarkLocalReproDisabled(b*testing.B) {
r:=Repro{false}
doLocalRepro(b, r)
}
funcBenchmarkDiscardV9(b*testing.B) {
varlog logr.Logger=logr.Discard()
doV9(b, log)
}
funcBenchmarkDiscardManualV9(b*testing.B) {
varlog logr.Logger=logr.Discard()
doManualV9(b, log)
}
What did you expect to see?
I expected all cases to show 0 allocations. It should be able to see that the variadic slice is only used if the log-level is enabled, and thereby elide the whole thing. It seems that works within a package but not across packages.
The text was updated successfully, but these errors were encountered:
thockin
changed the title
affected/package: Compiler optimization
affected/package: Compiler optimization across packages to avoid allocations
Nov 21, 2022
cherrymui
changed the title
affected/package: Compiler optimization across packages to avoid allocations
cmd/compile: optimization across packages to avoid allocations
Nov 21, 2022
The "local repro" doesn't do exactly what the logr function does. Specifically, Impl doesn't use the parameters, therefore does not escape them, unlike the actual logr function, which passes them to an interface call, which makes them escaped.
If I make the local repro does a similar interface call, like
// This is a simple repro all in one package.
type Repro struct {
enabled bool
impl interface { Impl(string, ...any) }
}
//go:noinline
func (r Repro) Info(msg string, keysAndValues ...interface{}) {
// It looks like the slice allocation is elided?
if r.enabled {
r.Impl(msg, keysAndValues...)
}
}
//go:noinline
func (r Repro) Impl(x string, a ...interface{}) {
r.impl.Impl(x, a...)
}
It then also allocates.
So I don't think crossing a package boundary is what matters here.
See also #53465 , which is somewhat related. If inlining happens (as mentioned in that issue), we should be able to not allocate, if that issue is fixed. If inlining does not happen, then we're making a call to a function that escapes parameters, so I'm not sure there is anything we can do to avoid the allocation.
I think there doesn't seem anything we can do beyond #53465. Tentatively closing. Feel free to reopen if I'm mistaken. Thanks.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Using github.com/go-logr/logr, I ran a benchmark that shows an optimization that is missing. In fact, we wrote the code this way because Russ et al said this optimization could be done in future, so this is not so much a bug report as it is a feature request.
Here is the benchamark:
What did you expect to see?
I expected all cases to show 0 allocations. It should be able to see that the variadic slice is only used if the log-level is enabled, and thereby elide the whole thing. It seems that works within a package but not across packages.
What did you see instead?
Allocations where they are not needed.
cc @pohly
The text was updated successfully, but these errors were encountered: