[]byte(string) 有多贵?

Posted

技术标签:

【中文标题】[]byte(string) 有多贵?【英文标题】:How expensive is []byte(string)? 【发布时间】:2012-12-31 16:05:41 【问题描述】:

让我们将string 转换为[]byte

func toBytes(s string) []byte 
  return []byte(s) // What happens here?

这种演员阵容有多贵?是否执行复制?据我在 Go 规范中看到的:字符串的行为类似于字节切片,但不可变,这至少应该涉及复制,以确保后续切片操作不会修改我们的字符串 s。反向对话会发生什么? []byte <-> string 对话是否涉及编码/解码,如 utf8 runes?

【问题讨论】:

我已经编写了一个基准here,概述了性能影响。 【参考方案1】:

[]byte(s) 不是演员表,而是conversion。一些转换与强制转换相同,例如uint(myIntvar),它只是重新解释位就地。不幸的是,字符串到字节切片转换的情况并非如此。字节切片是可变的,字符串(准确地说是字符串值)不是。结果是正在制作的字符串的必要副本(内存分配+内容传输)。所以是的,在某些情况下它可能会很昂贵。

编辑:不执行编码转换。字符串(源)字节按原样复制到切片(目标)字节。

【讨论】:

string 内部如何存储不是很清楚,是 utf8 还是 rune?你能说说这个吗? 来自golang.org/ref/spec#String_types:“字符串的元素具有字节类型,可以使用通常的索引操作进行访问。”。所以没有 UTF-8,没有符文。 String 是一个编号的字节序列,any 个字节。 OTOH,许多 stdlib 函数仅适用于 UTF-8 编码的字符串。 @demi 字符串的表示是一种字节数组。但是,字符串显然旨在包含 utf-8 编码:应用于字符串的 range 语句解码 utf-8 并返回代码点。 See here in the spec. "Programming in Go" 一书声称:[]byte(string) 的转换速度非常快 (O(1)),因为在后台,@ 987654330@ 可以简单地引用字符串的底层字节,不需要复制。反向转换也是如此,string([]byte); 再次没有复制底层字节,所以转换是 O(1)。" 所以看来这种说法是不正确的。 FWIW,有一个 open issue 请求一个功能,如果在 []byte(s) 转换后生成的字节数组从未被修改,它将使用字符串提供的底层数组而不是复制。从表面上看,这似乎是一个有用的优化。【参考方案2】:

转换复制字节,但它也为堆上的 []byte 分配空间。在将字符串反复转换为 []byte 的情况下,您可以通过重用 []byte 和使用 copy 命令来节省内存管理时间。 (参见http://golang.org/ref/spec#Appending_and_copying_slices 以及使用字符串作为源的特殊情况。)

在转换和复制命令的两种情况下,复制本身都是一个直字节复制,它应该运行得非常快。我希望编译器能够生成某种 CPU 高效执行的重复移动指令。

逆向转换,从字节片中生成字符串,肯定涉及在堆上分配字符串。不变性属性迫使这一点。有时您可以通过使用 []byte 做尽可能多的工作然后在最后创建一个字符串来进行优化。 bytes.Buffer 类型通常很有用。

现在追逐红鲱鱼,编码和 UTF-8 都不是问题。字符串和 []byte 都可以保存任意数据。副本不查看数据,它只是复制它。在说诸如字符串打算包含 UTF-8 或 鼓励这样的内容时,请谨慎选择词语。更准确的做法是简单地注意一些语言特性,例如 for 语句的范围子句,解释字符串为 UTF-8。只需了解将字符串解释为 UTF-8 和不解释的内容。字符串中有非 UTF-8 并且需要按字节进行范围?没问题,只是不要使用范围子句。

s := "string"
for i := 0; i < len(s); i++ 
    b := s[i]
    // work with b

这是惯用的 Go。它没有气馁,也没有违反任何意图。它只是逐字节迭代字符串,这有时正是您想要做的。

【讨论】:

【参考方案3】:

作为对上述答案的补充,在最新的go language specification中,string与数字类型之间的类型转换的特殊规则声明如下:

特定规则适用于数字类型之间或字符串类型之间的(非常量)转换。这些转换可能会改变 x 的表示并产生运行时成本。所有其他转换只改变 x 的类型,但不改变 x 的表示。

【讨论】:

以上是关于[]byte(string) 有多贵?的主要内容,如果未能解决你的问题,请参考以下文章

java方法调用有多贵

IOS - reloadData 有多贵?

NULL 指针参数有多贵?

线程有多贵?

“nodetool repair”操作有多贵?

命名管道(fifo)有多贵?