-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
目标和参考资料 #1
Comments
感谢。、 |
我的使用场景是这样,面对很多网络连接,先声明一个NewTimer ,然后用一个协程去Run,而后每一个连接打开的时候,使用TM.ScheduleFunc() 对每个连接进行不同时间的心跳,测试的时候是每个连接到来,每5秒下发一次心跳,一个连接没问题,超过一个连接,其他的连接发送了几次心跳后会莫名停止,就是TM.ScheduleFunc中执行的函数不执行了,众多连接只有一个连接能发送心跳,其他的都不能,请赐教,是不是我用的方式不对。 |
@jungeshidai go.mod是v0.0.4吧?可否发下调用代码,我测试下。 |
package main
import (
"encoding/hex"
"flag"
"fmt"
"github.com/antlabs/timer"
"net/http"
_ "net/http/pprof"
"log"
"time"
"github.com/panjf2000/gnet"
)
var (
SetBytes, _ = hex.DecodeString("01030000001445C5")
TM = timer.NewTimer()
)
type iotServer struct {
*gnet.EventServer
}
func (es *iotServer) OnInitComplete(srv gnet.Server) (action gnet.Action) {
log.Printf("Iot server is listening on %s (multi-cores: %t, loops: %d)\n", srv.Addr.String(), srv.Multicore, srv.NumEventLoop)
go ProfStart()
//启动时间轮
go TimeStart()
return
}
/*
消息处理函数
*/
func (es *iotServer) React(data []byte, c gnet.Conn) (out []byte, action gnet.Action) {
return
}
/*
连接打开时
*/
func (es *iotServer) OnOpened(c gnet.Conn) (out []byte, action gnet.Action) {
TM.ScheduleFunc(5*time.Second, func() {
fmt.Printf("开始下发指令:[%s]\n", c.RemoteAddr())
if c == nil {
return
}
err := c.AsyncWrite(SetBytes)
fmt.Printf("时间[%s]:[%s]:下发指令:%x\n", time.Now().Format("2006-01-02 15:04:05"), c.RemoteAddr(), SetBytes)
if err != nil {
c.Close()
}
})
return
}
/*
连接退出时
*/
func (es *iotServer) OnClosed(c gnet.Conn, err error) (action gnet.Action) {
return
}
/*
程序性能监控模块启动
*/
func ProfStart() {
http.ListenAndServe("0.0.0.0:6060", nil)
}
/*
时间轮模块启动
*/
func TimeStart() {
TM.Run()
}
func main() {
var port int
var multicore bool
flag.IntVar(&port, "port", 501, "--port 9000")
flag.BoolVar(&multicore, "multicore", true, "--multicore true")
flag.Parse()
iot := new(iotServer)
log.Fatal(gnet.Serve(iot, fmt.Sprintf("tcp://:%d", port), gnet.WithMulticore(multicore)))
} |
ok,我看下 |
@jungeshidai 下载v0.0.5版本看下呢,刚刚处理了下周期性定时器边界问题。 |
@guonaihong 目前测试看,问题已经修复,之前的0.4版本我已经再测试环境测试了性能问题,长期运行CPU占用0.7左右的。马上发布0.5的版本到测试服务器上测试,有问题再向您反馈,感谢。 |
@jungeshidai ok,客气了。 提问题可以建新的issue。一个问题一个issue,这样以后也可以帮助到别人检索问题和帮助。 |
目标
参考资料
论文
http://www.cs.columbia.edu/~nahum/w6998/papers/ton97-timing-wheels.pdf
参考项目
https://github.com/torvalds/linux/blob/v4.7/kernel/time/timer.c (linux 2.6内核引入时间轮)
https://github.com/cloudwu/skynet/blob/master/skynet-src/skynet_timer.c
https://github.com/RussellLuo/timingwheel
参考书本
书名
深入linux内核架构(Professional Linux Kernel Architecture)(第15章时间管理)
tv1 0-255
范围
tv2 2的8次方-2的14次方-1
tv3 2的14次方-2的20次方-1
tv4 2的20次方-2的26次方-1
tv5 2的26次方-2的32次方-1
移动
第一组的内容在最多256个时间周期之后就会耗尽,必须将后续各组的定时器依次前推,重新补足第一组。在第一组的索引位置恢复到初始位置0之后,会将第二组中一个数组项的所有定时器补充到第一组。这种做做法,解释了为什么各组选择了不同的时间间隔。因为第一组的各数组项可能有256个不同的到期时间,而第二组中一个数组项的数据就足以填充整个第一组的整个数组。该道理同样适用于后续各组。第三组的一个数组项的数据同样足以填充整修第二个组,第四组的一个数组项也足以填充整修第三组,而第五组的一个数组项也足以填充整个第四组。
后续各组的数组位置并非随机选择的,其中的索引项仍然发挥了作用。但索引项的值不再是每个时钟周期加1,而是第256的i-1次方
The text was updated successfully, but these errors were encountered: