定时器在游戏服务器中使用得非常普遍,它的效率直接影响了服务器的性能。对于服务器程序来说只有理解定时器的原理和细节才能更好的使用定时器,做到心中有数。在前面的文章中已经介绍过一种定时器算法-时间堆,本文介绍另一种定时器算法-时间轮。
一、时间轮(Timing-Wheel)算法原理
1.1 基本思想
我们把时间轮分为5个轮子(slots1~slots5),slots1 255个区间,其余4个slots分别为64个区间。每个区间都是链表,链表上挂了当前时刻要执行的所有tick。
注册时,根据触发时间,tick落到5个轮子其中一个, 轮子区间最大值分别为:slot1:2^8, slot2:2^14, slot3:2^20, slot4:2^26, slot5:2^32(区间数量和范围可调整)
例如:注册一个30秒的tick, 落到slot1;注册一个3600秒的tick,落到slot2
1.2 转动规则
- 可在进程主循环中推动时间轮的转动, 并附带上次执行到本次执行的时间差
- 从slots1的区间中依次取到期的tick执行
- slots1转一圈(256个区间),则slots2转1/64圈,也就是移1个区间;slots2转一圈(64次)slots3转1/64圈,此类推。若tick执行则从链表中删除,没执行则为tick重定位区间。再比如说slots2的63个区间中,0号区间上的tick是slots1走完一个周期(256次)需要执行的tick, 2号区间是slots1走完2个周期要执行的tick, slots2每移动1个区间会把当前区间的tick重定位到slots1中,以待遍历slots1区间的时候执行;
同理,slots3移动1次(需要slots2走一圈)并把当前区间的中的tick重定位到slots2各区间,以此类推。
二、核心代码:
1 | //nNextTickTime 触发时间(未来某个时间点,比如:18580082,因为精度问题,通常来说不会取unix时间戳;一般取系统启动以来毫秒或纳秒数) |