douchen7555 2014-11-13 10:13
浏览 56
已采纳

GoLang指针性能

The following code shows two benchmarks. The first one creates a struct by value in each iteration, while the second one does use a pointer to the struct.

Why is the latter 20x slower ?? I know about GC issues with GoLang, but shouldn't escape analysis handle those situations ?

I'm using go1.4beta1, but 1.3.3 gave me the [same - wrong] different results.

Any idea ?

package main

import "testing"

type Adder struct {
    vals []int
}

func (a *Adder) add() int {
    return a.vals[0] + a.vals[1]
}

func BenchmarkWithoutPointer(b *testing.B) {
    accum := 0
    for i := 0; i < b.N; i++ {
        adder := Adder{[]int{accum, i}}
        accum = adder.add()
    }
    _ = accum
}

func BenchmarkWithPointer(b *testing.B) {
    accum := 0
    for i := 0; i < b.N; i++ {
        adder := &Adder{[]int{accum, i}}
        accum = adder.add()
    }
    _ = accum
}

Benchmark go1.4.1:

 $ go test -bench=.                                                                                                                             

testing: warning: no tests to run
PASS
BenchmarkWithoutPointer 1000000000           2.92 ns/op
BenchmarkWithPointer    30000000            57.8 ns/op
ok      github.com/XXXXXXXXXX/bench/perf    5.010s

Benchmark go1.3.3:

testing: warning: no tests to run
PASS
BenchmarkWithoutPointer 500000000            7.89 ns/op
BenchmarkWithPointer    50000000            37.5 ns/op
ok      

EDIT:

Conclusion:

As Ainar-G said, the []int does escape to heap in the second benchmark. After reading a bit more about 1.4beta1 it seems, that new write barriers are introduced when accessing the heap caused by the new GC plans. But raw execution seems to have increased. Looking forward to 1.5 =).

  • 写回答

1条回答 默认 最新

  • dougekui1518 2014-11-13 10:30
    关注

    Running the benchmark with the -m gcflag gives the possible answer:

    ./main_test.go:16: BenchmarkWithoutPointer []int literal does not escape
    (...)
    ./main_test.go:25: []int literal escapes to heap
    

    Your []int in the second example escapes to heap, which is slower than stack. If you use separate x and y fields for your arguments instead of a slice

    type Adder struct {
        x, y int
    }
    
    func (a *Adder) add() int {
        return a.x + a.y
    }
    

    the benchmark shows the expected behaviour:

    BenchmarkWithoutPointer 1000000000               2.27 ns/op
    BenchmarkWithPointer    2000000000               1.98 ns/op
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 poi合并多个word成一个新word,原word中横版没了.
  • ¥15 求MCSCANX 帮助
  • ¥15 机器学习训练相关模型
  • ¥15 Todesk 远程写代码 anaconda jupyter python3
  • ¥15 我的R语言提示去除连锁不平衡时clump_data报错,图片以下所示,卡了好几天了,苦恼不知道如何解决,有人帮我看看怎么解决吗?
  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 VUE项目怎么运行,系统打不开