思考

相信大家在实际的项目开发中会遇到这么一个事,有的程序员写的代码不仅bug少,而且性能高;而有的程序员写的代码能否流畅的跑起来,都是一个很大问题。
而我们今天要讨论的就是一个关于性能优化的案例分析。

案例分析

我们先来构造一些基础数据(长度为10亿的切片,并赋上值):

var testData = GenerateData()// generate billion slice datafunc GenerateData() []int {    data := make([]int, 1000000000)    for key, _ := range data {        data[key] = key % 128    }    return data}// get lengthfunc GetDataLen() int {    return len(testData)}

案例一

// case onefunc CaseSumOne(result *int) {    data := GenerateData()    for i := 0; i < GetDataLen(); i++ {        *result += data[i]    }}
// case twofunc CaseSumTwo(result *int) {    data := GenerateData()    dataLen := GetDataLen()    for i := 0; i < dataLen; i++ {        *result += data[i]    }}

执行结果

$ go test -bench=.goos: windowsgoarch: amd64BenchmarkCaseSumOne-8                  1        7439749000 ns/opBenchmarkCaseSumTwo-8                  1        2529266700 ns/opPASSok      _/C_/go-code/perform/case-one   14.059s

问题分析

  • CaseSumTwo执行效率是CaseSumOne的2.94倍,快了近三倍,这是为什么呢?
  • 其实很容易猜到,这里有一个连续的函数调用“GetDataLen()”,

案例二

// case threefunc CaseSumThree(result *int) {    data := GenerateData()    dataLen := GetDataLen()    tmp := *result    for i:= 0; i < dataLen; i++ {        tmp += data[i]    }    *result = tmp}

执行

$ go test -bench=.goos: windowsgoarch: amd64BenchmarkCaseSumOne-8                  1        7439749000 ns/opBenchmarkCaseSumTwo-8                  1        2529266700 ns/opBenchmarkCaseSumThree-8                1        1657554600 ns/opPASSok      _/C_/go-code/perform/case-one   15.717s

待续