go strings/bytes: LastIndexByte is significantly slower than IndexByte

lztngnrs  于 4个月前  发布在  Go
关注(0)|答案(8)|浏览(41)

你正在使用的Go版本是什么( go version )?

$ go version
go version go1.13.1 darwin/amd64

这个问题在最新版本中是否会重现?

是的。

你正在使用什么操作系统和处理器架构( go env )?

两者都是Linux/MacOS。

你做了什么?

我正在使用multipart.NewReader()处理来自Cloud REST API的多部分响应。结果发现,大约1/3的时间被用在了mime/multipart/multipart.go中的scanUntilBoundary()函数 -> bytes.LastIndexByte()上。经过深入研究,这并不奇怪,因为bytes.LastIndexByte()没有使用任何优化,编译成了简单的字节到字节循环,Intel(或SSE)上没有使用REP SCASB指令。

你期望看到什么?

希望bytes.LastIndexByte()能使用SSE或者至少是REP SCASB优化过的代码。

你实际上看到了什么?

在汇编代码中看到的是简单的字节到字节循环。

u4dcyp6a

u4dcyp6a1#

感谢您报告这个问题。
IndexByte 的优化程度比 LastIndexByte 显著得多,它在可比基准测试中(即 IndexByte(aaaa...ax)IndexLastByte(xa...aaaa) 相比时,寻找 x )的速度约为7倍。
我想我们可以将相同的实现移植到 LastIndex 上。

j2qf4p5b

j2qf4p5b2#

我刚要为这个问题创建一个新的Issue,但注意到这个问题已经存在了。我发现这个Profile数据表明,LastIndexByte现在被广泛使用(例如在proto代码中),占据了整体CPU时间分析的很大一部分。

我同意我们应该优化字符串/字节的LastIndexByte,使其类似于IndexByte:

$x_{1e0f1}x$

ve7v8dk2

ve7v8dk23#

也许状态 = 需要修复?

vxbzzdmp

vxbzzdmp4#

我较早地分配给自己,因为我已经有了一个通过 ./all.bash 的原型,但需要在一台安静的机器上进行基准测试,并在发送审查之前对页面边界处理进行双重检查。

zynd9foi

zynd9foi5#

https://golang.org/cl/266538提到了这个问题:strings, bytes: use SIMD for LastIndexByte on amd64

dohp0rv5

dohp0rv56#

@martisch,你打算在某个时候合并那个CL吗?
你需要帮助进行测试/审查/基准测试吗?

relj7zay

relj7zay7#

我可以计划在下一个周期合并它。
我最后缺少的是一个测试,即数据开始处的页面边界得到尊重。如果有人能修改现有的测试(或助手)以创建一个测试字符串/字节片段,其中数据之前和之后的页面受到保护,这将有所帮助。上次我检查时,它只测试了一个方向,但最近测试已经发生了变化,我没有再次检查。
通过测试以受保护页面开头和结尾来确保使用SIMD的操作不读取太多数据,也将有助于现有代码,并可以成为一个独立的CL。

gcuhipw9

gcuhipw98#

https://go.dev/cl/522475提到了这个问题:internal/bytealg: add generic LastIndexByte{,String}

相关问题