64位无符号整数concat基准测试

时间:2017-03-28 22:09:59

标签: performance go benchmarking

我有一个调整问题。我的网络应用程序请求中有一些重复的代码片段,其中发生了 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。

我还在考虑检查两个整数的最大值,如果它们低于unsafeuint32的MAX,我可以自定义逻辑。手动uint16降级的基准测试大约是uint16,但这不现实,因为在Web请求本身中它仍然需要检查整数的大小并做额外的逻辑,可能会导致比23 ns/op获得更多的开销。

更新

我设法将其简化了一点:

7 ns/op

0 个答案:

没有答案