[go]timewheel选择
当系统定时任务很多的时候,用标准库的time会增加内存和cpu的使用,所以前辈提出了timewheel的东西,找了一下github上timewheel有挺多的。
看一下前几个
github.com/ouqiang/timewheel
代码超少200行,但是我不太喜欢他的的接口设计... 我是希望接口是和标准库一样的 func AfterFunc(d Duration, f func()) 他func AfterFunc(d Duration, args any) ;而且不支持定时任务
github.com/rfyiamcool/go-timewheel
支持定时任务;但是用的时候发现定时任务小于timewheel的tk的时候会失效,所以感觉不是很舒服
github.com/antlabs/timer
提供两种实现;默认timer,10ms检查一下任务感觉太频繁;min_heap实现,基本看到没有空跑cpu,感觉他的实现还是不错的(添加任务的时候唤醒运行线程,任务做完了让线程阻塞到下一个任务的触发时间);支持定时任务,支持自定义定时规则。我喜欢这个
测试了一下
package main
import (
"fmt"
"runtime"
"sync"
"time"
"github.com/antlabs/timer"
"github.com/rfyiamcool/go-timewheel"
)
func printMem() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d KB\n", m.Alloc/1024)
}
func main() {
count := 100000
d := time.Second * 3
fmt.Println("\ntimer")
printMem() // 输出2917 KB
newTimer := timer.NewTimer(timer.WithMinHeap())
var wg3 sync.WaitGroup
for i := 0; i < count; i++ {
wg3.Add(1)
newTimer.AfterFunc(d, func() {
wg3.Done()
})
}
go newTimer.Run()
printMem() //输出13859 KB
wg3.Wait()
newTimer.Stop()
runtime.GC()
printMem() // 输出3022 KB
fmt.Println("\ntimewheel")
printMem() // 3024 KB
var wg2 sync.WaitGroup
for i := 0; i < count; i++ {
wg2.Add(1)
timewheel.AfterFunc(d, func() {
wg2.Done()
})
}
printMem() // 30442 KB
wg2.Wait()
runtime.GC()
printMem() // 5957 KB
fmt.Println("\nstd time")
printMem() // 5959 KB
var wg sync.WaitGroup
for i := 0; i < count; i++ {
wg.Add(1)
time.AfterFunc(d, func() {
wg.Done()
})
}
printMem() // 18204 KB
wg.Wait()
runtime.GC()
printMem() // 30736 KB
}
测试结果内存方面timer是最好的,然后肉眼观察了一下cpu,标准库cpu会比其它两个高些。
挖坑
1. timewheel原理和实现
2. 为什么timer表现更好

浙公网安备 33010602011771号