Is there an efficient way to calculate execution time in golang? - go

I'm looking for the best way to calculate execution time in go.
func main() {
start := time.Now()
time.Sleep(time.Second * 2)
//something doing here
elapsed := time.Since(start)
fmt.Printf("page took %s", elapsed)
}
The code above works fine.
But when I use templates, I have to write it again for each template function.
Is there an efficient way of calculating execution time, including with templates?

If you are timing an entire function, then you can use defer to eliminate some of the repetitive code.
// timer returns a function that prints the name argument and
// the elapsed time between the call to timer and the call to
// the returned function. The returned function is intended to
// be used in a defer statement:
//
// defer timer("sum")()
func timer(name string) func() {
start := time.Now()
return func() {
fmt.Printf("%s took %v\n", name, time.Since(start))
}
}
func main() {
defer timer("main")() // <-- The trailing () is the deferred call
time.Sleep(time.Second * 2)
} // prints: main took 2s
Run the example on the playground.
The specification says this about deferred calls:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns,
The function value timer("main") is evaluated at the defer statement. The timer function records the current time and returns an anonymous function. The returned anonymous function is invoked immediately before the surrounding function returns. The anonymous function computes and prints the elapsed time.
Use runtime.Callers and runtime.CallersFrames to automatically get the name of the calling function.
// callerName returns the name of the function skip frames up the call stack.
func callerName(skip int) string {
const unknown = "unknown"
pcs := make([]uintptr, 1)
n := runtime.Callers(skip+2, pcs)
if n < 1 {
return unknown
}
frame, _ := runtime.CallersFrames(pcs).Next()
if frame.Function == "" {
return unknown
}
return frame.Function
}
// timer returns a function that prints the name of the calling
// function and the elapsed time between the call to timer and
// the call to the returned function. The returned function is
// intended to be used in a defer statement:
//
// defer timer()()
func timer() func() {
name := callerName(1)
start := time.Now()
return func() {
fmt.Printf("%s took %v\n", name, time.Since(start))
}
}
func main() {
defer timer()()
time.Sleep(time.Second * 2)
} // prints: main.main took 2s
Note that there is a runtime cost for getting the function name compared to using a string literal as in the first part of this answer. To avoid measuring the cost of getting the function name, timer gets the name before recording the start time.
Run the example on the playground.

The solution provided by Cerise Limón is perfect.
In addition, if you don't want to pass function name explicitly, you could accomplish it like this:
func SomeFunction(list *[]string) {
defer TimeTrack(time.Now())
// Do whatever you want.
}
func TimeTrack(start time.Time) {
elapsed := time.Since(start)
// Skip this function, and fetch the PC and file for its parent.
pc, _, _, _ := runtime.Caller(1)
// Retrieve a function object this functions parent.
funcObj := runtime.FuncForPC(pc)
// Regex to extract just the function name (and not the module path).
runtimeFunc := regexp.MustCompile(`^.*\.(.*)$`)
name := runtimeFunc.ReplaceAllString(funcObj.Name(), "$1")
log.Println(fmt.Sprintf("%s took %s", name, elapsed))
}
As a result, you would get:
SomeFunction took 15.483µs
For more information, Refer this article: Go Function Tracing
Share the knowledge. :)

Use init function
package main
import (
"fmt"
"time"
)
var start time.Time
func init() {
start = time.Now()
}
func getChars(s string) {
for _, c := range s {
fmt.Printf("%c at time %v\n", c, time.Since(start))
time.Sleep(10 * time.Millisecond)
}
}
func main() {
fmt.Println("main execution started at time", time.Since(start))
getChars("Hello")
fmt.Println("\nmain execution stopped at time", time.Since(start))
}

Efficient way to calculate execution time in golang
You can easily get the execution time on your console using a defer function
defer functions execute even if the code get an error so you always get the execution time.
time package is used to get the time difference.
func main() {
now := time.Now()
defer func() {
fmt.Println(time.Now().Sub(now))
}()
// Here you can do whatever you want
}
Or you can use this code
func main() {
now := time.Now()
defer func() {
fmt.Println(time.Since(now))
}()
// Here you can do whatever you want
}
check the code in Playground for more. I added some functionality to recover from an error at the same time print the execution time, even if in the case of a panic error.

Use this as a side reference for an average computation time in Golang
(for 10,100,1000 elements accordingly).
Accessing an element within an array (1/1/1 sec)
Binary/dictionary search (1/2/3 sec)
Simple loop/linear search (10/100/1,000 sec)
Quick Sort/Merge Sort/Heap Sort/Tim Sort (10/200/3,000 sec)
Bubble Sort/Insertion Sort/Selection Sort (100/10,000/1,000,000 sec)

Related

Check named return error using defer function

Hi I want to write a generic function to trace error message when a function returns error. So I wrote this:
func TraceError1(err *error) {
if err != nil && *err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}
func TraceError2(err error) {
if err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}
func foo() (err error) {
defer TraceError1(&err)
defer TraceError2(err)
fmt.Println("do something")
return fmt.Errorf("haha")
}
TraceError1 works but TraceError2 didn't. In my understanding, error is an interface so it is a pointer/address, why do I need to pass its address? Why TraceError2 cannot work? Thanks.
In case of TraceError1 you are passing a pointer to the named return value err. The pointer is non-nil, but the value it points at (err) is nil (at the time of defer). However, it is not yet evaluated (dereferenced) because TraceError1 has not yet been called. By the time the function does run (after foo returns) and the pointer gets dereferenced, the value of err has been updated (by the return statement inside foo).
However, in case of TraceError2, a nil interface value is passed, which will stay nil even when TraceError2 executes eventually.
Here is a simpler example:
package main
import "fmt"
func intByValue(i int) {
fmt.Printf("i = %d\n", i)
// ^--- `i` is an integer value
// --- whatever i was passed to the function, gets printed
}
func intByRef(i *int) {
var v int = *i // i is a pointer to an int, which gets dereferenced here
// the *address* where the actual value resides was passed
// while the address stays the same, its value can change before
// i is dereferenced, and its value stored in v.
fmt.Printf("i = %d\n", v)
}
func main() {
var i int
defer intByValue(i) // passed the *value* of i, which is 0 right now
defer intByRef(&i) // passed a *pointer* to i, which contains 0 right now
i = 100 // before intByRef could "dereference" its argument, the value that it
// contained has been updated
// intByRef gets called, dereferences the value, finds 100, prints it.
// intByValue gets called, finds 0, prints it
// result should be:
// i = 100
// i = 0
}
So unfortunately, if you want the ability to update the error (e.g. by returning a named return value) before it gets used by the deferred function, you are going to have to pass around pointers to the variable.
In other words, TraceError2 is simply not suited for your use case.
Edit: use correct terminology and (questionably) improve example code.
As go blog explained
The behavior of defer statements is straightforward and predictable.
There are three simple rules:
A deferred function's arguments are evaluated when the defer statement is evaluated.
Deferred function calls are executed in Last In First Out order after the surrounding function returns.
Deferred functions may read and assign to the returning function's named return values.
According to first point, when you call defer TraceError2(err) , that err = nil and that is the value pass to the TraceError2 function.
TraceError1(err *error) works because it is getting a pointer to err, and that pointer value is assigned before defer func TraceError1 is executed.
Simple example code to explain the behaviour.
package main
import (
"fmt"
"runtime"
)
func main() {
i := 0
defer func(i int) {
fmt.Printf("%d\n",i) //Output: 0
}(i)
defer func(i *int) {
defer fmt.Printf("%d\n",*i) //Output: 1
}(&i)
i++
}

Why when I timeout a function a defer is not called?

When I add a defer in a function I expect that it will be always called when the function ends.
I noticed that it does not happen when the function is times out.
package main
import (
"context"
"fmt"
"time"
)
func service1(ctx context.Context, r *Registry) {
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer func() {
r.Unset("service 1")
}()
r.Set("service 1")
go service2(ctx, r)
select {
case <-ctx.Done():
cancel()
break
}
}
func service2(ctx context.Context, r *Registry) {
defer func() {
r.Unset("service 2")
}()
r.Set("service 2")
time.Sleep(time.Millisecond * 300)
}
type Registry struct {
entries map[string]bool
}
func (r *Registry)Set(key string) {
r.entries[key] = true
}
func (r *Registry)Unset(key string) {
r.entries[key] = false
}
func (r *Registry)Print() {
for key, val := range r.entries {
fmt.Printf("%s -> %v\n", key, val)
}
}
func NewRegistry() *Registry {
r := Registry{}
r.entries = make(map[string]bool)
return &r
}
func main() {
r := NewRegistry()
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*200)
go service1(ctx, r)
// go service3(ctx, r)
select {
case <-ctx.Done():
fmt.Printf("context err: %s\n", ctx.Err())
cancel()
}
r.Print()
}
In the example above, the defer in service2() is never called and that's why the output is:
service 1 -> false
service 2 -> true
instead of
service 1 -> false
service 2 -> false
I understand that timeout means "stop executing" but it's reasonable to me execute deferred code. I could not find any explanation of this behavior.
And the second part of the question - how to modify the service or Registry to be resistant to such situations?
Answer of 1st part
Say you have a function f1() which uses defer to call f2(), i.e. defer f2() . The fact is that the f2 will be called if and only if f1 completes even if a run-time panic occurs. More specifically, look at go-defer.
Now our concern is about using defer in goroutine. We also have to remember that a go-routine exits if it's parent function completes of exits.
So if we use defer in a go-routine function, then if the parent fuction completes or exits, then go-routine function must exit. Since it exits (not completes) the defer statement will not execute. It will be clear we draw the state of your program.
As you see,
at 1st millisecond, service1() completes before others. So, service2() exits without executing defer statement and 'service 2' won't be set to false. Since service1() completes, it's defer will execute and 'service 1' will be set to false.
at 2nd millisecond, the main() completes and program finishes.
So we see how this program executes.
Answer of 2nd part
One possible solution i tried is increase time in service1() or decrease time in service2().

Golang Concurrency Issue

I am learning Golang concurrency and have written a program to display URL's in order. I expect the code to return
http://bing.com*
http://google.com*
But it always returns http:/google.com*** . As if the variable is being overwritten.Since i am using goroutines i would expect it to return both values at the sametime.
func check(u string) string {
tmpres := u+"*****"
return tmpres
}
func IsReachable(url string) string {
ch := make(chan string, 1)
go func() {
ch <- check(url)
}()
select {
case reachable := <-ch:
// use err and reply
return reachable
case <-time.After(3* time.Second):
// call timed out
return "none"
}
}
func main() {
var urls = []string{
"http://bing.com/",
"http://google.com/",
}
for _, url := range urls {
go func() {
fmt.Println(IsReachable(url))
}()
}
time.Sleep(1 * time.Second)
}
Two problems. First, you've created a race condition. By closing over the loop variable, you're sharing it between the thread running the loop and the thread running the goroutine, which is causing your described problem: by the time the goroutine that was started for the first URL tries to run, the value of the variable has changed. You need to either copy it to a local variable, or pass it as an argument, e.g.:
for _, url := range urls {
go func(url string) {
fmt.Println(IsReachable(url))
}(url)
}
Second, you said you wanted to display them "in order", which is not a goal generally compatible with concurrency/parallism, because you cannot control the order of parallel operations. If you want them in order, you should do them in order in a single thread. Otherwise, you'll have to collect the results, wait for all them to come back, then sort the results back into the desired order before printing them.

golang code insert/substitute

I like not to allow the code to repeat. But I have a situation, when I must repeat it in every function I want to measure execution time, and I can do nothing to it.
For example, a function:
func someFunc() {
start_time := time.Now()
defer fmt.Println("Execution time: %v", time.Now().Sub(start_time))
<... doing some bussiness ...>
}
Now I must repeat this two first strokes in every function (and in original they are more complicated because of calling a function name). So I cannot make a function which measures time, because i must use defer inside of it. I cannot make a function even for second stroke, cause in original it calls a function name in Println and that's why the resulting name will not be of needed function.
Is there any way to insert this code by some label or a template, for example, like this:
func someFunc() {
//go-insert measuretime.tmpl
<... doing some bussiness ...>
}
And measuretime.tmpl is:
start_time := time.Now()
defer fmt.Println("Execution time: %v", time.Now().Sub(start_time))
This trick might help: defer a call to a function returning a function enclosing the start time.
func elapsed() func() {
start := time.Now()
return func() {
fmt.Println("Duration was", time.Since(start))
}
}
Call it as follows:
defer elapsed()()
Have a play
Having said that, benchmarking is the usual way to measure performance in Go. See how to write benchmarks in Go.

Passing parameters to function closure

I'm trying to understand the difference in Go between creating an anonymous function which takes a parameter, versus having that function act as a closure. Here is an example of the difference.
With parameter:
func main() {
done := make(chan bool, 1)
go func(c chan bool) {
time.Sleep(50 * time.Millisecond)
c <- true
}(done)
<-done
}
As closure:
func main() {
done := make(chan bool, 1)
go func() {
time.Sleep(50 * time.Millisecond)
done <- true
}()
<-done
}
My question is, when is the first form better than the second? Would you ever use a parameter for this kind of thing? The only time I can see the first form being useful is when returning a func(x, y) from another function.
The difference between using a closure vs using a function parameter has to do with sharing the same variable vs getting a copy of the value. Consider these two examples below.
In the Closure all function calls will use the value stored in i. This value will most likely already reach 3 before any of the goroutines has had time to print it's value.
In the Parameter example each function call will get passed a copy of the value of i when the call was made, thus giving us the result we more likely wanted:
Closure:
for i := 0; i < 3; i++ {
go func() {
fmt.Println(i)
}()
}
Result:
3
3
3
Parameter:
for i := 0; i < 3; i++ {
go func(v int) {
fmt.Println(v)
}(i)
}
Result:
0
1
2
Playground: http://play.golang.org/p/T5rHrIKrQv
When to use parameters
Definitely the first form is preferred if you plan to change the value of the variable which you don't want to observe in the function.
This is the typical case when the anonymous function is inside a for loop and you intend to use the loop's variables, for example:
for i := 0; i < 10; i++ {
go func(i int) {
fmt.Println(i)
}(i)
}
Without passing the variable i you might observe printing 10 ten times. With passing i, you will observe numbers printed from 0 to 9.
When not to use parameters
If you don't want to change the value of the variable, it is cheaper not to pass it and thus not create another copy of it. This is especially true for large structs. Although if you later alter the code and modify the variable, you may easily forget to check its effect on the closure and get unexpected results.
Also there might be cases when you do want to observe changes made to "outer" variables, such as:
func GetRes(name string) (Res, error) {
res, err := somepack.OpenRes(name)
if err != nil {
return nil, err
}
closeres := true
defer func() {
if closeres {
res.Close()
}
}()
// Do other stuff
if err = otherStuff(); err != nil {
return nil, err // res will be closed
}
// Everything went well, return res, but
// res must not be closed, it will be the responsibility of the caller
closeres = false
return res, nil // res will not be closed
}
In this case the GetRes() is to open some resource. But before returning it other things have to be done which might also fail. If those fail, res must be closed and not returned. If everything goes well, res must not be closed and returned.
This is a example of parameter from net/Listen
package main
import (
"io"
"log"
"net"
)
func main() {
// Listen on TCP port 2000 on all available unicast and
// anycast IP addresses of the local system.
l, err := net.Listen("tcp", ":2000")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// Handle the connection in a new goroutine.
// The loop then returns to accepting, so that
// multiple connections may be served concurrently.
go func(c net.Conn) {
// Echo all incoming data.
io.Copy(c, c)
// Shut down the connection.
c.Close()
}(conn)
}
}

Resources