为了账号安全,请及时绑定邮箱和手机立即绑定

[]rune 和 strings.Builder 的字符串反转比字节数组慢

[]rune 和 strings.Builder 的字符串反转比字节数组慢

Go
牛魔王的故事 2023-03-15 15:32:09
我尝试/尝试了三种反转字符串的方法,使用 Runes 和就地交换。建议像这里这样的多个地方func ReverseWithRune(str string) string {    runes := []rune(str)    for i, j := len(runes)-1, 0; j < i; i, j = i-1, j+1 {        runes[i], runes[j] = runes[j], runes[i]    }    return string(runes)}使用 strings.Builderfunc ReverseWithBuilder(str string) string {    var ret strings.Builder    strLen := len(str)    ret.Grow(strLen)    for i := strLen - 1; i >= 0; i-- {        ret.WriteByte(str[i])    }    return ret.String()}使用从输入字符串末尾填充的字节数组func ReverseWithByteArray(str string) string {    strLen := len(str)    ret := make([]byte, strLen)    for i := strLen - 1; i >= 0; i-- {        ret[strLen-i-1] = str[i]    }    return string(ret)}我想ReverseWithRune,ReverseWithBuilder应该比.快ReverseWithByteArray。ReverseWithByteArray无复制、更少的分配等。但对于小的 9 或大的 99999 长度字符串,字节数组的基准测试总是更快。RuneArr_9-4           9545110       111.3 ns/op       16 B/op        1 allocs/opStringBuil_9-4       24685213       40.79 ns/op       16 B/op        1 allocs/opByteArr_9-4          23045233       52.35 ns/op       32 B/op        2 allocs/opRune_99999-4             1110     1002334 ns/op   507904 B/op        2 allocs/opStringBuil_99999-4       6679      179333 ns/op   106496 B/op        1 allocs/opByteArr_99999-4         12200       97876 ns/op   212992 B/op        2 allocs/op我的问题是为什么 rune 和 builder 方法没有更快,尽管迭代次数较少(lenght/2)和到位等。另一个明显的问题是,符文/生成器方法可以改进吗?可能是我在这里用错了。细节goos: linux goarch: amd64 cpu: Intel(R) Core(TM) i5-7200U CPU @2.50GHz go version: go1.19.2 linux/amd64我试图查看配置文件,它显示了slicerunetostring主要strings.Builder.WriteBytes的繁重操作。 字节反向也很大,但也是因为它有更多的操作。
查看完整描述

1 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

哪个更快并不那么重要,因为三分之二是不正确的。只有ReverseWithRune是正确的。


其他人操纵字符串中的各个字节。在 Go 中,字符串是 UTF-8 编码的,这是一种多字节编码。代码点超出 ASCII 范围的字符使用超过 1 个字节进行编码,如果逐字节反转它们,则会破坏该字符,因为反向多字节编码与正向编码并不相同。


您可以在 Go playground 上轻松检查它,使用"Hello, 世界"其标准示例中提供的字符串:


https://go.dev/play/p/oYfPsO-C_OR


输出:


ReverseWithByteArray ��疸� ,olleH

ReverseWithBuilder ��疸� ,olleH

ReverseWithRune 界世 ,olleH

至于为什么比较慢:它涉及创建一个(32 位整数)ReverseWithRune切片,然后将字符串复制到其中,同时从 UTF-8 编码解码字符边界。rune然后你反转它,然后分配一个新的字节数组,然后将一个切片编码rune为UTF-8。


查看完整回答
反对 回复 2023-03-15
  • 1 回答
  • 0 关注
  • 47 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信