Quick Guide to Benchmarking Process and Tools

September 20, 2018 

Quick Guide to Benchmarking Process and Tools

What is Benchmarking?

Benchmarks help to measure the performance of code by running it multiple times and counting an average of vital stats. Benchmark is a tool provided by the testing package so that there is no additional dependency to get started. These benchmark functions should be prefixed by “Benchmark” followed by the function name -

func BenchmarkLoop(b *testing.B){ write code here}

Benchmark runs and displays three things -

  • Time taken by each benchmark function available in a benchmarking file.
  • Time Taken by all the benchmark of application.
  • Reveals PASS or FAIL status for each benchmark of our application.

What is Sub-BenchMark?

Sub-Benchmark is a process in which a further benchmark function defined inside a benchmark. Benchmark defined inside another benchmark can be in the runnable state by using a run method code. Make a call to run method to run a benchmark written, inside another benchmark.

Example-



func BenchmarkAppendFloat(b *testing.B) {

    benchmarks := []struct{

        name    string

        float   float64

        fmt     byte

        prec    int

        bitSize int

    }{

        {"Decimal", 33909, 'g', -1, 64},

        {"Float", 339.7784, 'g', -1, 64},

        {"Exp", -5.09e75, 'g', -1, 64},

        {"NegExp", -5.11e-95, 'g', -1, 64},

        {"Big", 123456789123456789123456789, 'g', -1, 64},

        ...

  }

    dst := make([]byte, 30)

    for _, bm := range benchmarks {

        b.Run(bm.name, func(b *testing.B) {

            for i := 0; i < b.N; i++ {

                AppendFloat(dst[:0], bm.float, bm.fmt, bm.prec, bm.bitSize)

            }

        })

    }

}


Explanation of the above code

In an above code benchmark is defined and named as a "BenchmarkAppendFloat".

Then further sub benchmark is defined inside a benchmark like as -



 b.Run(bm.name, func(b *testing.B)

This sub benchmark is making use of values defined in a benchmark to execute a sub-benchmark. To execute sub benchmarks, these are as same as benchmarks. When the main benchmark method runs, the sub benchmarks defined in the main benchmark method will run automatically. When BenchMark runs, then the sub benchmark will run for each mentioned value defined in the primary benchmark.

The following command can be used to run these -


go test -bench=.

After execution of sub benchmark by using the above command, the result will appear in the following format. The result is visible as above. The main benefit of using a sub-benchmark is the elimination of writing different benchmarks to execute benchmarks with different values. Write a single benchmark and run this benchmark with any number of benefits by using the concept of sub benchmark.

Measurement of benchmark

Basically, by default benchmark executed by nanoseconds and can also change this benchmarking execution time mentioned below. Benchmark implemented by following parameters and can define a benchmark time in a different format while executing code.

  • Nanoseconds
  • Microseconds
  • Milliseconds
  • Seconds
  • Minutes
  • Hours
  • Days

Benefits of Enabling Benchmarking

  • It helps to check that how much amount of memory defined method talking(method defined in form of BenchMarking).
  • It helps to check that how much amount of CPU iteration our system is taking.
  • While using BenchMarking, it can also be defined that in how much amount of memory defined method should run.
  • Usage of BenchMarking will be cleared more by reading a complete documentation.

How Benchmarking Works?

Write Code in form of functions according to requirements.

Write BenchMarks for written methods of code in the file with extension


Filename_test.go.

Test all the BenchMark present in the file for functions of code go test -bench=.

Test all the BenchMarks present in the file along with Memory and CPU Profiling for functions of code.


Go test -run =. -bench = .cpuprofile = cpu.out -benchmem - memprofile = mem.out.
  • After execution of the above command result for CPU Profiling will store in a cpu.out and result for Memory Profiling will get stored in mem.out.
  • Execution of the following command helps to access the content of cpu.out and mem.out file.
  • Execute go tool pprof cpu.out for CPU Profiling.
  • Execute go tool pprof mem.out for Memory Profiling.

How to Adopt BenchMarking?

Steps to be followed to write benchmarks or sub benchmarks -

  • The code runs correctly without defining the primary file in the project.
  • Write a benchmarking function in a separate file for functions defined in a project.
  • But there is a condition that this benchmark file saved with “ _test” in the end.
  • “Filename_test.go”

Benchmarks method contains a signature in the following format -


func BenchmarkLoop(b *testing.B){ write code here}

After that, we can run a benchmarking for project code by using the following command -


go test -bench=.

After execution of code by using the above command, the result will be available in the following format

Commands to execute benchmarks -

CPU profiling and memory profiling on our code along with benchmarking by using following steps -

  • Write code according to according to requirements.
  • Then go to the specific location to run a code, where code placed.
  • Then after this run the following command.

go test -run=. -bench=. -cpuprofile=cpu.out -benchman -memprofile=mem.out -trace trace.out

Explanation of result -

  • The first row containing the name of the method.
  • The second row contains many iterations.
  • The third parameter contains the value that how much each benchmark uses CPU resource.
  • The last column represents that how much memory allocated to each method in the form of bytes.
  • The last column represents that how much memory allocated to each method in form of bytes.
  • Add the following line of code to perform memory profiling results along with CPU profiling.
  • b.ReportAllocs()

The last two columns in above screenshot representing a memory regarding information. These previous two columns in a screenshot are visible only because the above line of code is added within the code. If the above line of code not inserted into code then a last two columns in output are not visible.

Allocate static memory for the code -

To run a code/function with some defined memory requirements. Define the amount of memory within a function. Following the line of code can be added inside the function to allocate some specific resource for the code.

b.SetBytes(2)


Benefits of Benchmarking

  • It helps to check that amount of memory defined.
  • It helps to check that how much amount of CPU iteration system takes.
  • BenchMarking determines how much amount of memory defined method should run.
  • Improved Productivity
  • Improved Performance
  • Impact Analysis
  • Process Intelligence
  • Community Intelligence
  • Quantitative and Quantitative approach

Best Practises of Benchmarking

  • Cloning of the project
  • Adhere to standard and meaningful metrics
  • Improve Operations
  • Have a deadline
  • Strategic Alignment and Assessment
  • Team Management
  • Great Decision-Making
  • Determine Process and gather data
  • Limit Server connections
  • Analysis of gaps and Improvement
  • Determine Future Trends
  • Reveal Results
  • Implementation of plans and Result Monitoring
  • Continuous Evaluation of Benchmarks