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.

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

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?