-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: runtime.growslice optimization does not work with named slice types #53888
Comments
This bug affects \cc @ianlancetaylor |
@dsnet Which versions of Go does this affect? |
Go1.18.4 up to and including HEAD (go1.19-558785a0a9) |
Interesting. This benchmark only allocates once as expected: func BenchmarkGeneric2(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s = nil
genericExtend2(s, n)
}
}
func genericExtend2[T any](s []T, n int) []T {
return append(s[:cap(s)], make([]T, n)...)[:len(s)]
}
It seems that somehow |
Okay, the following fixes the optimization: func genericExtend[S ~[]E, E any](s S, n int) S {
return S(append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)])
} where we directly cast |
More details: It seems that this is unrelated to generics, but rather that the growslice optimization simple does not work with named slices. This benchmark also allocates twice and does not use generics: func BenchmarkConcrete2(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s = nil
bytesExtend2(s, n)
}
}
type S []byte
func bytesExtend2(s S, n int) S {
return append(s[:cap(s)], make(S, n)...)[:len(s)]
}
|
Change https://go.dev/cl/417494 mentions this issue: |
I looked briefly into what was going with the compiler. It seems that this is a bug in the type-checker. If the expression is |
Change https://go.dev/cl/418475 mentions this issue: |
Change https://go.dev/cl/418514 mentions this issue: |
…e for const exprs So we don't have to depend on typecheck pass to fixup the concrete type for some constant expressions. Previously, the problem won't show up, until CL 418475 sent, which removes an un-necessary type conversion in "append(a, b...) to help the optimization kicks in. For #53888 Change-Id: Idaecd38b7abbaa3ad5b00ff3b1fb0fd8bbeb6726 Reviewed-on: https://go-review.googlesource.com/c/go/+/418514 Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
Change https://go.dev/cl/422037 mentions this issue: |
Updates #53888 Change-Id: I34ef2c5bd23816e1991cfec2bef4cae72676b523 Reviewed-on: https://go-review.googlesource.com/c/go/+/422037 Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]>
Change https://go.dev/cl/422040 mentions this issue: |
Same as CL 418475, but for Unified IR. Updates #53888 Fixes #54337 Change-Id: I31d5a7af04d8e3902ed25db85009d46ea4c38dbe Reviewed-on: https://go-review.googlesource.com/c/go/+/422040 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Than McIntosh <[email protected]>
…e for const exprs So we don't have to depend on typecheck pass to fixup the concrete type for some constant expressions. Previously, the problem won't show up, until CL 418475 sent, which removes an un-necessary type conversion in "append(a, b...) to help the optimization kicks in. For golang#53888 Change-Id: Idaecd38b7abbaa3ad5b00ff3b1fb0fd8bbeb6726 Reviewed-on: https://go-review.googlesource.com/c/go/+/418514 Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
There's no need for a and b to match types. The typechecker already ensured that a and b are both slices with the same base type, or a and b are (possibly named) []byte and string. The optimization to treat append(b, make([], ...)) as a zeroing slice extension doesn't fire when there's a OCONVNOP wrapping the make. Fixes golang#53888 Change-Id: Ied871ed0bbb8e4a4b35d280c71acbab8103691bc Reviewed-on: https://go-review.googlesource.com/c/go/+/418475 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Keith Randall <[email protected]>
Updates golang#53888 Change-Id: I34ef2c5bd23816e1991cfec2bef4cae72676b523 Reviewed-on: https://go-review.googlesource.com/c/go/+/422037 Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]>
Same as CL 418475, but for Unified IR. Updates golang#53888 Fixes golang#54337 Change-Id: I31d5a7af04d8e3902ed25db85009d46ea4c38dbe Reviewed-on: https://go-review.googlesource.com/c/go/+/422040 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Than McIntosh <[email protected]>
Repeatedly calling Grow on a slice with sufficient capacity should effectively be a noop. However, this was not the case since it would zero out the elements between the length and capacity. Avoid that behavior to ensure Grow remains cheap in the common case. Also provide a workaround for golang/go#53888 to ensure that the number of allocations when growing is always 1. Fixes golang/go#53853 Change-Id: Id52c0d50ae9a97fe8af9acfeb666360859f336c0 Reviewed-on: https://go-review.googlesource.com/c/exp/+/417494 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Eli Bendersky <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Joseph Tsai <[email protected]>
Using 558785a
Consider the following benchmark:
Running these produces:
There's an additional allocation in
BenchmarkGeneric
overBenchmarkConcrete
,even though the benchmarks are semantically equivalent where
bytesExtend
is identical togenericExtend[[]byte]
.The compiled logic for
genericExtend[[]byte]
contains a call toruntime.makeslice
that does not exist inbytesExtend
.\cc @randall77
The text was updated successfully, but these errors were encountered: