Table of Contents
Golang Performance Benchmarking
Command
go test -bench=.
Example Fibonacci number
package main
import "fmt"
func fibo(n int) int {
if n == 1 {
return 0
}
if n == 2 {
return 1
}
return fibo(n-1) + fibo(n-2)
}
func fiboOptimized(n int, hist map[int]int) int {
if n == 1 {
return 0
}
if n == 2 {
return 1
}
if _, found := hist[n-1]; !found {
hist[n-1] = fiboOptimized(n-1, hist)
}
if _, found := hist[n-2]; !found {
hist[n-2] = fiboOptimized(n-2, hist)
}
return hist[n-1] + hist[n-2]
}
func main() {
// Fibonacci sequence
// 0, 1, 1, 2, 3,
// 5, 8, 13, 21, 34,
// 55, 89, 144, 233, 377,
// 610
n := 70
answer := fibo(n)
fmt.Printf("Basic Fibonacci of %d is %d\n", n, answer)
hist := make(map[int]int)
optAnswer := fiboOptimized(n, hist)
fmt.Printf("Optimized Fibonacci of %d is %d\n", n, optAnswer)
}
*********************
Output
*********************
Basic Fibonacci of 30 is 514229
Optimized Fibonacci of 30 is 514229
Benchmarking Results
// file name : fibonacci_test.go
package main
import "testing"
func BenchmarkFibo(b *testing.B) {
for i := 0; i < b.N; i++ {
fibo(40)
}
}
func BenchmarkFiboOptimized(b *testing.B) {
for i := 0; i < b.N; i++ {
hist := make(map[int]int)
fiboOptimized(40, hist)
}
}
*********************
Output
*********************
#go test -bench=.
goos: darwin
goarch: arm64
pkg: goexample/recursion1/fibo
BenchmarkFibo-8 4 250860427 ns/op
BenchmarkFiboOptimized-8 511828 2241 ns/op
PASS
ok goexample/recursion1/fibo 3.625s
Explanation
1. Environment Information
goos: darwin
: Indicates the operating system used for the benchmark. In this case, “Darwin” means the test was run on macOS.goarch: arm64
: Specifies the CPU architecture. “arm64” refers to a 64-bit ARM architecture, often used in modern Apple M1/M2 processors.
2. Package Information
pkg: goexample/recursion1/fibo
: Indicates the Go package or module being tested. The package path isgoexample/recursion1/fibo
, where your benchmark code resides.
3. Benchmark Results
For each benchmark function, you get the following details:
a. BenchmarkFibo-8
This is the benchmark for your fibo
function:
516
: The number of iterations Go was able to execute during the benchmark run.2051322 ns/op
: The average time taken per iteration, measured in nanoseconds. 2051322 ns=2.051 ms2051322 \, \text{ns} = 2.051 \, \text{ms}2051322ns=2.051ms.- This relatively high value reflects the inefficiency of
fibo
‘s naive recursive implementation.
- This relatively high value reflects the inefficiency of
b. BenchmarkFiboOptimized-8
This is the benchmark for your fiboOptimized
function:
633816
: The number of iterations Go was able to execute during the benchmark run.1833 ns/op
: The average time taken per iteration, measured in nanoseconds. 1833 ns=0.001833 ms1833 \, \text{ns} = 0.001833 \, \text{ms}1833ns=0.001833ms.- This low value demonstrates the significant performance improvement due to memoization.
4. Thread Parallelism
The -8
suffix (e.g., BenchmarkFibo-8
) indicates the number of parallel CPU threads available to the benchmarking process. Here, 8
threads were available for execution, as determined by Go’s runtime during the benchmark.
5. PASS
This indicates that the tests were successfully executed, and there were no panics or unexpected errors during the benchmark.
Summary
- Performance Gap:
fibo
: ~2.051 ms per call, executed 516 times.fiboOptimized
: ~0.001833 ms per call, executed 633,816 times.- The optimized function is significantly faster due to memoization, reducing redundant computations.
- Key Insights:
- The naive
fibo
implementation becomes exponentially slower as nnn increases, which is evident from the high time per operation. - The memoized
fiboOptimized
scales linearly with nnn, as shown by its drastically lower time per operation.
- The naive
Please visit https: https://codeandalgo.com for more such contents.
Leave a Reply