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.
Related
I had this code:
defer common.LogWarning(
"b09ee123-f18b-46a8-b80d-f8361771178d:",
resp.Body.Close(), // gets called immediately, is *not* deferred..
)
and common.LogWarning is simply like this:
func LogWarning(uuid string, err error) {
if err != nil {
log.Warning(uuid, err)
}
}
the problem is that resp.Body.Close() gets called immediately - that call is not deferred, so how does this work? Why is not the whole code block get deferred?
From the documentation:
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.
The defer statement defers the function call. The arguments to the function are evaluated immediately.
Use an anonymous function to accomplish your goal:
defer func() {
common.LogWarning("b09ee123-f18b-46a8-b80d-f8361771178d:",
resp.Body.Close())
}()
The call represented by the trailing () is deferred.
defer defers the execution of a function until the current function returns. The arguments to the function are evaluated immediately.
https://tour.golang.org/flowcontrol/12
If you need to defer a code block where all evaluations are to be deferred, make it a function:
defer func() {
// Stuff to defer here
}()
``
I have two goroutines go doProcess_A() and go doProcess_B(). Both can call saveData(), a non goroutine method.
should I use go saveData() instead of saveData() ?
Which one is safe?
var waitGroup sync.WaitGroup
func main() {
for i:=0; i<4; i++{
waitGroup.Add(2)
go doProcess_A(i)
go doProcess_B(i)
}
waitGroup.Wait()
}
func doProcess_A(i int) {
// do process
// the result will be stored in data variable
data := "processed data-A as string"
uniqueFileName := "file_A_"+strconv.Itoa(i)+".txt"
saveData(uniqueFileName, data)
waitGroup.Done()
}
func doProcess_B(i int) {
// do some process
// the result will be stored in data variable
data := "processed data-B as string"
uniqueFileName := "file_B_"+strconv.Itoa(i)+".txt"
saveData(uniqueFileName, data)
waitGroup.Done()
}
// write text file
func saveData(fileName ,dataStr string) {
// file name will be unique.
// there is no chance to be same file name
err := ioutil.WriteFile("out/"+fileName, []byte(dataStr), 0644)
if err != nil {
panic(err)
}
}
here, does one goroutine wait for disk file operation when other goroutine is doing?
or, are two goroutine make there own copy of saveData() ?
Goroutines typically don't wait for anything except you explicitly tell them to or if an operation is waiting on a channel or other blocking operation. In your code there is a possibility of a race condition with unwanted results if multiple goroutines call the saveData() function with same filename. It appears that the two goroutines are writing to different files, therefore as long as the filenames are unique, the saveData operation will be safe in a goroutine. It doesn't make sense to use a go routine to call saveData(), don't unnecessarily complicate your life, just call it directly in the doProcess_X functions.
Read more about goroutines and make sure you are using it where it is absolutely necessary. - https://gobyexample.com/goroutines
Note: Just because you are writing a Go application doesn't mean you
should litter it with goroutines. Read and understand what problem it
solves so as to know the best time to use it.
What is the use of defer in Go? The language documentation says it is executed when the surrounding function returns. Why not just put the code at end of given function?
We usually use defer to close or deallocate resources.
A surrounding function executes all deferred function calls before it returns, even if it panics. If you just place a function call at the end of a surrounding function, it is skipped when panic happens.
Moreover a deferred function call can handle panic by calling the recover built-in function. This cannot be done by an ordinary function call at the end of a function.
Each deferred call is put on stack, and executed in reverse order when the surrounding function ends. The reversed order helps deallocate resources correctly.
The defer statement must be reached for a function to be called.
You can think of it as another way to implement try-catch-finally blocks.
Closing like try-finally:
func main() {
f, err := os.Create("file")
if err != nil {
panic("cannot create file")
}
defer f.Close()
// no matter what happens here file will be closed
// for sake of simplicity I skip checking close result
fmt.Fprintf(f,"hello")
}
Closing and panic handling like try-catch-finally
func main() {
defer func() {
msg := recover()
fmt.Println(msg)
}()
f, err := os.Create(".") // . is a current directory
if err != nil {
panic("cannot create file")
}
defer f.Close()
// no matter what happens here file will be closed
// for sake of simplicity I skip checking close result
fmt.Fprintf(f,"hello")
}
The benefit over try-catch-finally is that there is no nesting of blocks and variable scopes. This simplifies the structure of the surrounding function.
Just like finally blocks, deferred function calls can also modify the return value if they can reach the returned data.
func yes() (text string) {
defer func() {
text = "no"
}()
return "yes"
}
func main() {
fmt.Println(yes())
}
There are already good answers here. I would like to mention one more use case.
func BillCustomer(c *Customer) error {
c.mutex.Lock()
defer c.mutex.Unlock()
if err := c.Bill(); err != nil {
return err
}
if err := c.Notify(); err != nil {
return err
}
// ... do more stuff ...
return nil
}
The defer in this example ensures that no matter how BillCustomer returns, the mutex will be unlocked immediately prior to BillCustomer returning. This is extremely useful because without defer you would have to remember to unlock the mutex in every place that the function could possibly return.
ref.
Well, it's not always guaranteed that your code may reach the end of the function (e.g. an error or some other condition may force you to return well ahead of the end of a function). The defer statement makes sure that whatever function is assigned to it gets executed for sure even if the function panics or the code returns well before the end of the function.
The defer statement also helps keep the code clean esp. in cases when there are multiple return statements in a function esp. when one needs to free resources before return (e.g. imagine you have an open call for accessing a resource at the beginning of the function - for which a corresponding close must be called before the function returns for avoiding a resource leak. And say your function has multiple return statements, maybe for different conditions including error checking. In such a case, without defer, you normally would call close for that resource before each return statement). The defer statement makes sure the function you pass to it is always called irrespective of where the function returns, and thus saves you from extraenous housekeeping work.
Also defer can be called multiple times in the same function. E.g.: In case you have different resources being allocated through your function which need to be eventually freed before returning, then you can call defer for each of them after allocation and these functions are executed in the reverse order of the sequence in which they were called when the function exits.
Key benefit of using defer - it will be called any way no matter how function will return. If an extraordinary situation would occur deferred function will be called.
So it gives nice things:
Recover after panic. This allows yes realize try ... catch behavior.
Not to forget clean up (close files, free memory, etc) before normal exit. You may open some resource and you have to close it before exit. But function can have several exit points - so you have to add freeing in every return point. That’s very tedious in maintenance. Or you can put only one deferred statement - and resources will be released automatically.
Summary:
When we do certain operations that need cleanup, we can "schedule" the cleanup operations which would be run when the function returns no matter which path that happens, including due to panic.
Detailed answer:
Programming languages strive to provide constructs that facilitate simpler and less error-prone development. (E.g. why should Golang support garbage collection when we can free the memory ourselves)
A function can return at multiple points. The user might overlook doing certain cleanup operations in some paths
Some cleanup operations are not relevant in all return paths
Also, it is better to keep the cleanup code closer to the original operation which needed the cleanup
When we do certain operations that need cleanup, we can "schedule" the cleanup operations which would be run when the function returns no matter which path that happens.
A defer statement defers the execution of a function until the
surrounding function returns.
This example demonstrates defer functionality:
func elapsed(what string) func() {
start := time.Now()
fmt.Println("start")
return func() {
fmt.Printf("%s took %v\n", what, time.Since(start))
}
}
func main() {
defer elapsed("page")()
time.Sleep(time.Second * 3)
}
Out:
start
page took 3s
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)
What happened when defer called twice when the struct of that method has been changed?
For example:
rows := Query(`SELECT FROM whatever`)
defer rows.Close()
for rows.Next() {
// do something
}
rows = Query(`SELECT FROM another`)
defer rows.Close()
for rows.Next() {
// do something else
}
which rows when the last rows.Close() called?
It depends on the method receiver and on the type of the variable.
Short answer: if you're using the database/sql package, your deferred Rows.Close() methods will properly close both of your Rows instances because Rows.Close() has pointer receiver and because DB.Query() returns a pointer (and so rows is a pointer). See reasoning and explanation below.
To avoid confusion, I recommend using different variables and it will be clear what you want and what will be closed:
rows := Query(`SELECT FROM whatever`)
defer rows.Close()
// ...
rows2 := Query(`SELECT FROM whatever`)
defer rows2.Close()
I'd like to point out an important fact that comes from the deferred function and its parameters being evaluated immedately which is stated in the Effective Go blog post and in the Language Spec: Deferred statements too:
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, in the reverse order they were deferred.
If variable is not a pointer: You will observe different results when calling a method deferred, depending if the method has a pointer receiver.
If variable is a pointer, you will see always the "desired" result.
See this example:
type X struct {
S string
}
func (x X) Close() {
fmt.Println("Value-Closing", x.S)
}
func (x *X) CloseP() {
fmt.Println("Pointer-Closing", x.S)
}
func main() {
x := X{"Value-X First"}
defer x.Close()
x = X{"Value-X Second"}
defer x.Close()
x2 := X{"Value-X2 First"}
defer x2.CloseP()
x2 = X{"Value-X2 Second"}
defer x2.CloseP()
xp := &X{"Pointer-X First"}
defer xp.Close()
xp = &X{"Pointer-X Second"}
defer xp.Close()
xp2 := &X{"Pointer-X2 First"}
defer xp2.CloseP()
xp2 = &X{"Pointer-X2 Second"}
defer xp2.CloseP()
}
Output:
Pointer-Closing Pointer-X2 Second
Pointer-Closing Pointer-X2 First
Value-Closing Pointer-X Second
Value-Closing Pointer-X First
Pointer-Closing Value-X2 Second
Pointer-Closing Value-X2 Second
Value-Closing Value-X Second
Value-Closing Value-X First
Try it on the Go Playground.
Using a pointer variable the result is always good (as expected).
Using a non-pointer variable and using pointer receiver we see the same printed results (the latest) but if we have value receiver, it prints 2 different results.
Explanation for non-pointer variable:
As stated, deferred function including the receiver is evaluated when the defer executes. In case of a pointer receiver it will be the address of the local variable. So when you assign a new value to it and call another defer, the pointer receiver will be again the same address of the local variable (just the pointed value is different). So later when the function is executed, both will use the same address twice but the pointed value will be the same, the one assigned later.
In case of value receiver, the receiver is a copy which is made when the defer executed, so if you assign a new value to the variable and call another defer, another copy will be made which is different from the previous one.
Effective Go mentions:
The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes, not when the call executes.
Besides avoiding worries about variables changing values as the function executes, this means that a single deferred call site can defer multiple function executions
In your case, the defer would reference the second rows instance.
The two deferred functions are executed in LIFO order (as mentioned also in "Defer, Panic, and Recover").
As icza mentions in his answer and in the comments:
The 2 deferred Close() methods will refer to the 2 distinct Rows values and both will be properly closed because rows is a pointer, not a value type.
Ah I see, the rows always refer to the last one, http://play.golang.org/p/_xzxHnbFSz
package main
import "fmt"
type X struct {
A string
}
func (x *X) Close() {
fmt.Println(x.A)
}
func main() {
rows := X{`1`}
defer rows.Close()
rows = X{`2`}
defer rows.Close()
}
Output:
2
2
So maybe the best way to preserve the object is to pass it to a function: http://play.golang.org/p/TIMCliUn60
package main
import "fmt"
type X struct {
A string
}
func (x *X) Close() {
fmt.Println(x.A)
}
func main() {
rows := X{`1`}
defer func(r X) { r.Close() }(rows)
rows = X{`2`}
defer func(r X) { r.Close() }(rows)
}
Output:
2
1
Most of the time, you should be able to just add a block, that way you don't have to worry about thinking of a new variable name, and you don't have to worry about any of the items not being closed:
rows := Query(`SELECT FROM whatever`)
defer rows.Close()
for rows.Next() {
// do something
}
{
rows := Query(`SELECT FROM another`)
defer rows.Close()
for rows.Next() {
// do something else
}
}
https://golang.org/ref/spec#Blocks