基准测试时指针接收器不比值接收器快

时间:2016-10-30 11:40:10

标签: pointers go

这是我正在测试的代码,我希望看到在基准测试时,基于指针的addDataPointer执行速度比基于addData值的函数要快。为什么两者之间的绩效没有重大变化?

package main

import "fmt"

type BigStruct struct {
    name string
    data []byte
}

func addData(s BigStruct) BigStruct {
    s.data = append([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, s.data...)
    return BigStruct{name: s.name, data: s.data}
}

func (s *BigStruct) addDataPointer() {
    s.data = append([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, s.data...)
}

func main() {
    a := BigStruct{name: "greg", data: []byte("abc")}
    b := &BigStruct{name: "greg", data: []byte("abc")}
    fmt.Println(addData(a))
    b.addDataPointer()
    fmt.Println(*b)
}

func BenchmarkBigLenPointer(b *testing.B) {
    for i := 0; i < b.N; i++ {
        big := &BigStruct{name: "greg", data: []byte(strings.Repeat("test1234", 1024))}
        big.addDataPointer()
    }
}

func BenchmarkBigLen(b *testing.B) {
    for i := 0; i < b.N; i++ {
        big := BigStruct{name: "greg", data: []byte(strings.Repeat("test1234", 1024))}
        addData(big)
    }

1 个答案:

答案 0 :(得分:1)

您的基准测试函数会测量for循环内的任何内容,例如:

    big := &BigStruct{name: "greg", data: []byte(strings.Repeat("test1234", 1024))}
    big.addDataPointer()

    big := BigStruct{name: "greg", data: []byte(strings.Repeat("test1234", 1024))}
    addData(big)

因此,您还会对strings.Repeat()进行基准测试,这会为您提供较长的string值,并将其转换为[]byte,后者会复制此string这个冗长的addDataPointer()

这些的执行时间远远大于addData()方法和strings.Repeat()函数的执行时间。

将转化和for调用移到func BenchmarkBigLenPointer(b *testing.B) { s := []byte(strings.Repeat("test1234", 1024)) for i := 0; i < b.N; i++ { big := &BigStruct{name: "greg", data: s} big.addDataPointer() } } func BenchmarkBigLen(b *testing.B) { s := []byte(strings.Repeat("test1234", 1024)) for i := 0; i < b.N; i++ { big := BigStruct{name: "greg", data: s} addData(big) } } 循环之外,如下所示:

addData()

现在,更准确地衡量方法和功能的时间。但即使您对此进行基准测试,您也会得到基准测试结果,表明addDataPointer()<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>{% block title %}Welcome!{% endblock %}</title> {% block stylesheets %}{% endblock %} <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" /> </head> <body> {% block header %} {% endblock %} {% block body %}{% endblock %} {% block footer %}{% endblock %} {% block javascripts %}{% endblock %} </body> </html> 的执行时间非常接近。

对此的解释是,在函数的情况下,您传递包含字节切片的struct值。 Go中的切片是小描述符(struct like headers),它不包含切片的元素,只包含指向后备数组的指针。因此,无论其长度(元素数量)如何,切片值的大小都是相同的。要查看切片标头内的内容,请查看reflect.SliceHeader类型。

因此函数的开销很小,这可能会给它的执行时间带来一些影响,但另一方面指针方法需要取消引用指针,这会增加执行时间。最后,他们非常接近。在这种情况下没有太大区别。