duanqiechui2378 2016-10-30 11:40
浏览 42
已采纳

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

Here is the code I'm testing, I was expecting to see that when bench marking, the pointer based addDataPointer would perform faster than the addData value based function. Why is there no significant changes in performance between the two?

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条回答 默认 最新

  • dongye9228 2016-10-30 12:21
    关注

    Your benchmark functions measure whatever is inside the for loops, e.g.:

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

    And:

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

    So you also benchmark strings.Repeat(), which gives you a long string value, and you also convert it to []byte, which makes a copy of this lengthy string.

    The execution times of these are much bigger than the execution times of your addDataPointer() method and addData() function.

    Move the conversion and strings.Repeat() call outside of the for loops, something like this:

    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)
        }
    }
    

    Now this is more accurate to measure the time of your method and function. But even when you benchmark this, you will get benchmark results that show that execution times of both addData() and addDataPointer() are very close.

    The explanation for this is that in case of the function you pass a struct value containing a byte slice. Slices in Go are small descriptors (struct like headers), which do not contain the elements of the slices but only a pointer to a backing array. So the size of a slice value is the same, regardless of its length (number of elements). To see what's inside a slice header, check out the reflect.SliceHeader type.

    So the overhead of the function is little, which might give a little to its execution time, but the pointer method on the other hand needs to dereference the pointer, which adds a little to its execution time. In the end, they are very close. In this case there is not much difference.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 MIT控制器能控制不稳定系统吗
  • ¥15 公司代码X对业务伙伴X无效,处理方法?
  • ¥15 微信内链接跳转到浏览器打开怎么实现
  • ¥15 三角波可以直接加施密特电路整形到矩形波吗实物
  • ¥15 html,php,在使用html请求php文件时发生了错误,无法请求到php文件读取数据库并用javascript进行数据显示,刷新
  • ¥15 touchsocket udp组播
  • ¥20 MAC怎么安装Silverlight 插件?以及安装了怎么启用
  • ¥15 VS2012中查询语句无法填入解析,数值传不进去
  • ¥15 gis系统开发出现命名空间“ESRI.ArcGIS”中不存在类型或命名空间名“Analyst3D”报错
  • ¥15 怎么让ai定时给我发信息 c#或者python