这是我正在测试的代码,我希望看到在基准测试时,基于指针的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)
}
答案 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
类型。
因此函数的开销很小,这可能会给它的执行时间带来一些影响,但另一方面指针方法需要取消引用指针,这会增加执行时间。最后,他们非常接近。在这种情况下没有太大区别。