英文:
golang: optimal sorting and joining strings
问题
这段go源代码中的一个短方法有一个注释,暗示它在内存分配方面不是最优的。
这是Join
方法的源代码。
这里到底是在进行低效的内存分配?我没有看到避免分配源字符串切片和目标字节切片的方法。源字符串切片是键的切片,目标字节切片是字节的切片。
英文:
This short method in go's source code has a comment which implies that it's not allocating memory in an optimal way.
> ... could do better allocation-wise here ...
This is the source code for the Join
method.
What exactly is inefficiently allocated here? I don't see a way around allocating the source string slice and the destination byte slice. The source being the slice of keys. The destination being the slice of bytes.
答案1
得分: 1
这个代码片段在内存使用方面是高效的。任何分配都是在strings.Join
中进行的,而strings.Join
被编写成最小化内存分配。
我怀疑这个注释是从net/http包中的这段代码中意外复制粘贴过来的:
// TODO: could do better allocation-wise here, but trailers are rare,
// so being lazy for now.
if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
return err
}
这段代码可能会进行以下分配:
- 在strings.Join中创建的
[]byte
,用于构造结果 - strings.Join返回的字符串转换结果
- 表达式
"Trailer: "+strings.Join(keys, ",")+"\r\n"
的字符串结果 - 在io.WriteString中使用的
[]byte
转换结果
更节省内存的方法是为要写入的数据分配一个单独的[]byte
。
n := len("Trailer: ") + len("\r\n")
for _, s := range keys {
n += len(s) + 1
}
p := make([]byte, 0, n-1) // 减去1是为了len(keys) - 1个逗号
p = append(p, "Trailer: "...)
for i, s := range keys {
if i > 0 {
p = append(p, ',')
}
p = append(p, s...)
}
p = append(p, "\r\n"...)
w.Write(p)
英文:
The code referenced by the comment is memory efficient as written. Any allocations are in strings.Join
which is written to minimize memory allocations.
I suspect that the comment was accidentally copied and pasted from this code in the net/http package:
// TODO: could do better allocation-wise here, but trailers are rare,
// so being lazy for now.
if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
return err
}
This snippet has the following possible allocations:
[]byte
created in strings.Join for constructing the resultstring
conversion result returned by strings.Join- string result for expression
"Trailer: "+strings.Join(keys, ",")+"\r\n"
- The
[]byte
conversion result used in io.WriteString
A more memory efficient approach is to allocate a single []byte
for the data to be written.
n := len("Trailer: ") + len("\r\n")
for _, s := range keys {
n += len(s) + 1
}
p := make([]byte, 0, n-1) // subtract 1 for len(keys) - 1 commas
p = append(p, "Trailer: "...)
for i, s := range keys {
if i > 0 {
p = append(p, ',')
}
p = append(p, s...)
}
p = append(p, "\r\n"...)
w.Write(p)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论