Kimmo Hintikka
Kimmo Hintikka

Reputation: 15430

How to test Go function execution time using standard lib

I've written the following function that when used with Defer will surely do the trick but is there something in standard library I could use for this? I'm looking something similar to Python timeit which I could use directly from the shell?

package main

import (
    "fmt"
    "time"
)

func main() {
    defer timeTrack(time.Now(), "looptest")
    nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    var m []int
    for n := range nums {
        if n%2 == 0 {
            m = append(m, n)
        }
    }
}

func timeTrack(start time.Time, name string) {
    elapsed := time.Since(start)
    fmt.Printf("%s took %s", name, elapsed)
}

Upvotes: 6

Views: 3509

Answers (3)

peterSO
peterSO

Reputation: 166569

Use the Go testing package. For example,

main.go:

package main

func doStuff() {
    nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    var m []int
    for n := range nums {
        if n%2 == 0 {
            m = append(m, n)
        }
    }
}

func main() {
    doStuff()
}

main_test.go:

package main

import "testing"

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

Output:

$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: main
BenchmarkStuff-4    5000000    276 ns/op    120 B/op    4 allocs/op

Using the information from the benchmark, you can improve performance. Reduce the number and size of allocations by using an estimate to initialize slice m.

func doStuff() {
    nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    m := make([]int, 0, len(nums)/2+1)
    for n := range nums {
        if n%2 == 0 {
            m = append(m, n)
        }
    }
}

Output:

$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: main
BenchmarkStuff-4    20000000    83.1 ns/op    48 B/op    1 allocs/op

Upvotes: 7

zitryss
zitryss

Reputation: 148

You may use the "benchmark"-approach:

  1. Name the file %SOMETHING%_test.go

  2. Write tests, benchmarks, examples in it as follows:

    package main
    
    import (
        "testing"
    )
    
    func fn() {
        nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
        var m []int
        for n := range nums {
            if n%2 == 0 {
                m = append(m, n)
            }
        }
    }
    
    func BenchmarkFunc(b *testing.B) {
        for i := 0; i < b.N; i++ {
            fn()
        }
    }
    
  3. Open the terminal and execute the following command:

    go test -bench .
    
  4. You will see the output like this:

    goos: darwin
    goarch: amd64
    BenchmarkFunc-2      5000000           360 ns/op         120 B/op          4 allocs/op
    PASS
    ok      command-line-arguments  2.190s
    

Upvotes: 0

A.Bau
A.Bau

Reputation: 82

You can use testing

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

Upvotes: 4

Related Questions