Original: https://gocn.io/article/403
I saw some classmates talking about time in Xie da Group. After the leakage of the problem, even if the time is not released, an instant stunned, can not help to do the test, the results found that should not be so scary, there is a risk of leakage but not a leak, first look at the API description:
After waits for the duration to elapse and then sends the current time
//on the returned channel.
It's equivalent to Newtimer (d). C.
The underlying timer is not recovered by the garbage collector
//until the timer fires. If efficiency is a concern, use Newtimer
//instead and call Timer.stop if the Timer is no longer needed.
Func after (d Duration) <-chan time {
return Newtimer (d). C
}
mentions the underlying timer is not recovered by the garbage collector, which is quite scary will not be recycled by GC, but there are conditions until the timer fires, stating that fire will be back Received, the so-called fire is to time, write an example to prove the pressure yajing:
Package main
import ' time '
func main () {for
{
<-time. After (Ten * time. nanosecond)
}
}
The display memory is stable at 5.3mb,cpu of 161% and is definitely recycled by GC. Of course, if put in goroutine is also no problem, the same will be recycled:
Package main
Import "Time"
func main () {for
I: = 0; i <; i++ {
go func () {
<-time . After (Ten * time. nanosecond)}}
()
} time
. Sleep (1 * time. Hour)
}
Only resource consumption will be a bit more, CPU is 422%, memory occupies 6.4MB. So:
Remark:time. After (d) The fire is made after d time and then collected by GC, without causing a resource leak.
So what does the API say if Efficieny is a concern, what does user Newtimer instead and call Timer.stop mean? This is because of the general time. After is used in select, if another branch runs faster, the timer is not released immediately (after expiration), such as this:
Select {Case Time
. After (3*time. Second):
return errtimeout case
Packet: = Packetchannel:
//Process packet.
}
If there is a lot of packet, then always go to the following branch, the above timer will not be released immediately but in 3 seconds to release, and the following code:
Package main
import ' time '
func main () {for
{
Select {case
<-time. After (3 * time. Second):
Default:}}
}
This time, the equivalent will accumulate 3 seconds of the timer is not released, will continue to build and release the timer, the memory will stabilize at 2.8GB, this is certainly not the best, you can voluntarily release:
Package main
import ' time '
func main () {for
{
T: = time. Newtimer (3*time. Second)
Select {Case
<-t.c:
default:
t.stop ()
}}}
This will not occupy 2.8GB of memory, only about 5MB. Therefore, summarize the following note: GC will definitely recycle Time.after, after D is recycled. It would be nice to let the system recycle itself in general. If there is a problem with efficiency, you should use the timer to actively stop when it is not needed. Most of the time we don't have to think about it.
Hand in your homework.