時間輪算法定時器 antlabs-timer 介紹
推薦理由
當業務要處理大量的定時任務時,如果每個任務都創建一個 Golang 原生的 timer 的話,會佔用較多的 cpu 資源,這類場景,可以用時間輪算法優化 timer 的資源消耗。本次介紹一款多級時間輪庫 antlabs/timer(以下 timer 特指 antlabs/timer 庫),處理類似場景的優化。
功能介紹
timer 最小的時間粒度是 10ms, antlabs/timer 支持以下功能:
-
一次性定時,類似 time.AfterFunc;
-
週期性執行,類似 time.Ticker;
-
取消單個任務;
-
停止所有任務。
使用指南
安裝
go get github.com/antlabs/timer
代碼示例
下面是一個簡單的例子:
package main
import (
"log"
"time"
"github.com/antlabs/timer"
)
func main() {
tm := timer.NewTimer()
// 一次性執行,2s後執行
tm.AfterFunc(2*time.Second, func() {
log.Printf("2 time.Second")
})
// tk3 會被 tk3.Stop()函數調用取消掉
tk3 := tm.AfterFunc(3*time.Second, func() {
log.Printf("3 time.Second")
})
tk3.Stop() //取消tk3
// 週期執行,每1s執行一次
tm.ScheduleFunc(1*time.Second, func() {
log.Printf("schedule\n")
})
tm.Run()
}
timer 使用起來是比較簡單的,根據業務場景選擇合適的接口就好。
benchmark
Golang 1.14 對定時器做了優化,每個 P 維護一個定時器,減少了添加刪除任務時的鎖競爭,但是和本文介紹的 timer 庫對比起來還是有些耗資源,下面是 benchmark 的結果:
Golang 版本:1.16.6
cpu: Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
Benchmark_antlabs_Timer_AddTimer
Benchmark_antlabs_Timer_AddTimer/N-1m
Benchmark_antlabs_Timer_AddTimer/N-1m-8 9226951 116.6 ns/op 80 B/op 1 allocs/op
Benchmark_antlabs_Timer_AddTimer/N-5m
Benchmark_antlabs_Timer_AddTimer/N-5m-8 9589074 153.9 ns/op 80 B/op 1 allocs/op
Benchmark_antlabs_Timer_AddTimer/N-10m
Benchmark_antlabs_Timer_AddTimer/N-10m-8 9621186 167.0 ns/op 80 B/op 1 allocs/op
Benchmark_Stdlib_AddTimer
Benchmark_Stdlib_AddTimer/N-1m
Benchmark_Stdlib_AddTimer/N-1m-8 4967716 220.0 ns/op 81 B/op 1 allocs/op
Benchmark_Stdlib_AddTimer/N-5m
Benchmark_Stdlib_AddTimer/N-5m-8 5265825 237.9 ns/op 80 B/op 1 allocs/op
Benchmark_Stdlib_AddTimer/N-10m
Benchmark_Stdlib_AddTimer/N-10m-8 7703940 230.8 ns/op 80 B/op 1 allocs/op
總結
timer 利用時間輪算法,通過降低定時器精度的方式,將同一個時間單位內的任務集中存儲到一個雙向鏈表,可以一次鎖操作處理,減少鎖競爭,進而提高性能,對於業務中有大量定時任務,同時對精度要求大於 10ms 的場景,可以嘗試 timer 庫來優化。
參考資料
-
https://github.com/antlabs/timer
-
https://spongecaptain.cool/post/widget/timingwheel/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/emNifkcdn9oRjVHRcQmK9w