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

我尝试/尝试了三种反转字符串的方法,使用 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.Builder


func 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/op

StringBuil_9-4       24685213       40.79 ns/op       16 B/op        1 allocs/op

ByteArr_9-4          23045233       52.35 ns/op       32 B/op        2 allocs/op


Rune_99999-4             1110     1002334 ns/op   507904 B/op        2 allocs/op

StringBuil_99999-4       6679      179333 ns/op   106496 B/op        1 allocs/op

ByteArr_99999-4         12200       97876 ns/op   212992 B/op        2 allocs/op

我的问题是

  1. 为什么 rune 和 builder 方法没有更快,尽管迭代次数较少(lenght/2)和到位等。

  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的繁重操作。 

http://img.mukewang.com/641174cb0001351e06580336.jpg

字节反向也很大,但也是因为它有更多的操作。



牛魔王的故事
浏览 56回答 1
1回答

大话西游666

哪个更快并不那么重要,因为三分之二是不正确的。只有ReverseWithRune是正确的。其他人操纵字符串中的各个字节。在 Go 中,字符串是 UTF-8 编码的,这是一种多字节编码。代码点超出 ASCII 范围的字符使用超过 1 个字节进行编码,如果逐字节反转它们,则会破坏该字符,因为反向多字节编码与正向编码并不相同。您可以在 Go playground 上轻松检查它,使用"Hello, 世界"其标准示例中提供的字符串:https://go.dev/play/p/oYfPsO-C_OR输出:ReverseWithByteArray ��疸� ,olleHReverseWithBuilder ��疸� ,olleHReverseWithRune 界世 ,olleH至于为什么比较慢:它涉及创建一个(32 位整数)ReverseWithRune切片,然后将字符串复制到其中,同时从 UTF-8 编码解码字符边界。rune然后你反转它,然后分配一个新的字节数组,然后将一个切片编码rune为UTF-8。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go