如何对init()函数进行基准测试

I was playing with following Go code which calculates Population count using lookup table:

package population

import (
        "fmt"
)

var pc [256]byte

func init(){
        for i := range pc {
                pc[i] = pc[i/2] + byte(i&1)
        }
}

func countPopulation() {
        var x uint64 = 65535
        populationCount := int(pc[byte(x>>(0*8))] +
                pc[byte(x>>(1*8))] +
                pc[byte(x>>(2*8))] +
                pc[byte(x>>(3*8))] +
                pc[byte(x>>(4*8))] +
                pc[byte(x>>(5*8))] +
                pc[byte(x>>(6*8))] +
                pc[byte(x>>(7*8))])

        fmt.Printf("Population count: %d
", populationCount)
}

I have written following benchmark code to check performance of above code block:

package population

import "testing"

func BenchmarkCountPopulation(b *testing.B) {
        for i := 0; i < b.N; i++ {
                countPopulation()
        }
}

Which gave me following result:

100000             18760 ns/op
PASS
ok      gopl.io/ch2     2.055s

Then I moved the code from init() function to the countPopulation() function as below:

func countPopulation() {
        var pc [256]byte

        for i := range pc {
                pc[i] = pc[i/2] + byte(i&1)
        }

        var x uint64 = 65535
        populationCount := int(pc[byte(x>>(0*8))] +
                pc[byte(x>>(1*8))] +
                pc[byte(x>>(2*8))] +
                pc[byte(x>>(3*8))] +
                pc[byte(x>>(4*8))] +
                pc[byte(x>>(5*8))] +
                pc[byte(x>>(6*8))] +
                pc[byte(x>>(7*8))])

        fmt.Printf("Population count: %d
", populationCount)
}

and once again ran the same benchmark code, which gave me following result:

100000             20565 ns/op
PASS
ok      gopl.io/ch2     2.303s

After observing both the results it is clear that init() function is not in the scope of benchmark function. That's why first benchmark execution took lesser time compared to second execution.

Now I have another question which I am looking to get answer for.

If I need to benchmark only the init() method, considering there can be multiple init() functions in a package. How is it done in golang?

Thanks in advance.

Yes there can be multiple init()'s in a package, in-fact you can have multiple init()'s in a file. More information about init can be found here. Remember that init() is automatically called one time before your program's main() is even started.

The benchmark framework runs your code multiple times (in your case 100000). This allows it to measure very short functions, as well as very long functions. It doesn't make sense for benchmark to include the time for init(). The problem you are having is that you are not understanding the purpose of benchmarking. Benchmarking lets you compare two or more separate implementations to determine which one is faster (also you can compare performance based on input of the same function). It does not tell you where you should be doing that.

What you are basically doing is known as Premature Optimization. It's where you start optimizing code trying to make it as fast as possible, without knowing where your program actually spends most of its time. Profiling is the process of measuring the time and space complexity of a program. In practice, it allows you to see where your program is spending most of its time. Using that information, you can write more efficient functions. More information about profiling in go can be found in this blog post.