golang: optimal sorting and joining strings

huangapple go评论85阅读模式
英文:

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:

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)

huangapple
  • 本文由 发表于 2017年1月2日 16:09:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/41423272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定