我有一个调整问题。我的网络应用程序请求中有一些重复的代码片段,其中发生了 time_namelookup: 0.001
time_connect: 0.037
time_appconnect: 0.000
time_pretransfer: 0.037
time_redirect: 0.000
time_starttransfer: 0.092
----------
time_total: 0.164
等简单的事情。
现在我做了一些基准测试并测试了一个字节写入器,它非常慢(~400 ns / op)。 fmt.Sprintf("%d%d", 01293123, 234993923)
本身约为240 ns / op。然后我做了字符串加入:
sprintf
已经有了很大改进。但后来我尝试将2个整体转换为字节的混合
var concatBuffStr []byte
func BenchmarkStringsJoin(b *testing.B) {
for n := 0; n < b.N; n++ {
concatBuffStr = []byte(strings.Join([]string{
strconv.Itoa(2),
strconv.Itoa(3),
}, " "))
}
}
152 ns/op
惊人!但我可以避免将它们粘合在一起,并且已经保留了完整的16个字节,最多可以存储2个64位的空间:
var concatBuffStr []byte
func BenchmarkConcatIntsAsBytes(b *testing.B) {
for n := 0; n < b.N; n++ {
aBuf := make([]byte, 8)
bBuf := make([]byte, 8)
binary.BigEndian.PutUint64(aBuf, uint64(2))
binary.BigEndian.PutUint64(bBuf, uint64(3))
concatBuffStr = append(aBuf, bBuf...)
}
}
57.8 ns/op
到目前为止,我们比使用var concatBuffStr []byte
func BenchmarkCopyIntsAsBytes(b *testing.B) {
for n := 0; n < b.N; n++ {
concatBuffStr = make([]byte, 16)
bBuf := make([]byte, 8)
binary.BigEndian.PutUint64(concatBuffStr, uint64(123123))
binary.BigEndian.PutUint64(bBuf, uint64(3453455))
copy(concatBuffStr[8:], bBuf)
}
}
30.4 ns/op
方法快8倍。
想知道是否有比这更快的方式。我想避免fmt.Sprintf()
tho。
我还在考虑检查两个整数的最大值,如果它们低于unsafe
或uint32
的MAX,我可以自定义逻辑。手动uint16
降级的基准测试大约是uint16
,但这不现实,因为在Web请求本身中它仍然需要检查整数的大小并做额外的逻辑,可能会导致比23 ns/op
获得更多的开销。
更新
我设法将其简化了一点:
7 ns/op