Skip to content

Instantly share code, notes, and snippets.

@FZambia
Created September 10, 2019 14:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FZambia/fd81177660ed49a9b0da9521a1325501 to your computer and use it in GitHub Desktop.
Save FZambia/fd81177660ed49a9b0da9521a1325501 to your computer and use it in GitHub Desktop.
Go language timer pool
package timers
import (
"sync"
"time"
)
var timerPool sync.Pool
// AcquireTimer from pool.
func AcquireTimer(d time.Duration) *PoolTimer {
v := timerPool.Get()
if v == nil {
return newTimer(d)
}
tm := v.(*PoolTimer)
if tm.Reset(d) {
panic("Received an active timer from the pool!")
}
return tm
}
// ReleaseTimer to pool.
func ReleaseTimer(tm *PoolTimer) {
timerPool.Put(tm)
}
// PoolTimer ...
type PoolTimer struct {
*time.Timer
read bool
}
// MarkRead must be called after receiving value from timer chan.
func (t *PoolTimer) MarkRead() {
t.read = true
}
// Reset timer safely.
func (t *PoolTimer) Reset(d time.Duration) bool {
stopped := t.Stop()
if !stopped && !t.read {
<-t.C
}
t.Timer.Reset(d)
t.read = false
return stopped
}
func newTimer(d time.Duration) *PoolTimer {
return &PoolTimer{
Timer: time.NewTimer(d),
}
}
package timers
import (
"testing"
"time"
)
func BenchmarkPool(b *testing.B) {
for i := 0; i < b.N; i++ {
tm := AcquireTimer(time.Microsecond)
<-tm.C
tm.MarkRead()
ReleaseTimer(tm)
}
b.StopTimer()
b.ReportAllocs()
}
func BenchmarkStd(b *testing.B) {
for i := 0; i < b.N; i++ {
tm := time.NewTimer(time.Microsecond)
<-tm.C
}
b.StopTimer()
b.ReportAllocs()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment