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: treat "d = append(make([]T, 0, len(s)), s...)" as "d = make([]T, len(s)); copy(d, s)" #46079
Comments
Looks like the difference is that the faster code is able to elide zeroing the allocation. |
I dont think its clear cut we should do this. I would rather prefer that programmers wanting the increased performance write make+copy directly. Otherwise we will go down a path of adding more and more complexity rewriting append patterns in the compiler that are more idiomatic in my opinion to be written as e.g. make+copy in the first place. |
FWIW, I don't think I will, however, point out that except for the func copy[S SliceOf[T], T any](dst, src S) int {
n := len(src)
if n > len(dst) {
n = len(dst)
}
_ = append(dst[:0], src[:n]...)
return n
} In contrast, So it seems to me much more natural for users to reach for At any rate, given that |
But the allocation in the example here is explicitly not done by The suggestion here is not to rewrite Once generics are around a slices.Clone function might ideally take care of a more concise expression to clone a slice in one expression. Another way to write a slice clone is |
It would be great if the same optimization also works for the following two func InsertVerbose(s []int, k int, vs ...int) []int {
if n := len(s) + len(vs); n <= cap(s) {
s2 := s[:n]
copy(s2[k+len(vs):], s[k:])
copy(s2[k:], vs)
return s2
}
s2 := make([]int, len(s) + len(vs))
copy(s2, s[:k])
copy(s2[k:], vs)
copy(s2[k+len(vs):], s[k:])
return s2
}
func InsertVerbose_b(s []int, k int, vs ...int) []int {
if n := len(s) + len(vs); n <= cap(s) {
s2 := s[:n]
copy(s2[k+len(vs):], s[k:])
copy(s2[k:], vs)
return s2
}
s2 := make([]int, 0, len(s) + len(vs))
s2 = append(s2, s[:k]...)
s2 = append(s2, vs...)
s2 = append(s2, s[k:]...)
return s2
} [update]: func MergeSlices(data ...[]int) []int {
n := 0
for _, s := range data {
n += len(s)
}
r := make([]int, 0, n)
for _, s := range data {
r = append(r, s...)
}
return r
} |
Not sure whether or not the following make call reset elements: s := make([]byte, len(aString) + len(aByteSlice))
copy(s, aString)
copy(s[len(aString):], aByteSlice) [update] After some investigations, if looks the element in |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What did you do?
What did you expect to see?
No performance difference between the two ways.
What did you see instead?
The larger the length of the slices, the bigger performance difference between the two.
[Edit]: it looks the allocated bytes/op is the not same for the last two benchmarks. Bug or some inaccuracy?
The text was updated successfully, but these errors were encountered: