你正在使用的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优化过的代码。
你实际上看到了什么?
在汇编代码中看到的是简单的字节到字节循环。
8条答案
按热度按时间u4dcyp6a1#
感谢您报告这个问题。
IndexByte
的优化程度比LastIndexByte
显著得多,它在可比基准测试中(即IndexByte(aaaa...ax)
与IndexLastByte(xa...aaaa)
相比时,寻找x
)的速度约为7倍。我想我们可以将相同的实现移植到
LastIndex
上。j2qf4p5b2#
我刚要为这个问题创建一个新的Issue,但注意到这个问题已经存在了。我发现这个Profile数据表明,LastIndexByte现在被广泛使用(例如在proto代码中),占据了整体CPU时间分析的很大一部分。
我同意我们应该优化字符串/字节的LastIndexByte,使其类似于IndexByte:
$x_{1e0f1}x$
ve7v8dk23#
也许状态 = 需要修复?
vxbzzdmp4#
我较早地分配给自己,因为我已经有了一个通过 ./all.bash 的原型,但需要在一台安静的机器上进行基准测试,并在发送审查之前对页面边界处理进行双重检查。
zynd9foi5#
https://golang.org/cl/266538提到了这个问题:
strings, bytes: use SIMD for LastIndexByte on amd64
dohp0rv56#
@martisch,你打算在某个时候合并那个CL吗?
你需要帮助进行测试/审查/基准测试吗?
relj7zay7#
我可以计划在下一个周期合并它。
我最后缺少的是一个测试,即数据开始处的页面边界得到尊重。如果有人能修改现有的测试(或助手)以创建一个测试字符串/字节片段,其中数据之前和之后的页面受到保护,这将有所帮助。上次我检查时,它只测试了一个方向,但最近测试已经发生了变化,我没有再次检查。
通过测试以受保护页面开头和结尾来确保使用SIMD的操作不读取太多数据,也将有助于现有代码,并可以成为一个独立的CL。
gcuhipw98#
https://go.dev/cl/522475提到了这个问题:
internal/bytealg: add generic LastIndexByte{,String}