定时器的设计的几种思路

定时器的设计的几种思路

原文:高效定时器的设计_青萍之末的博客-CSDN博客

文章目录

一、timerfd二、定时器的概念三、排序链表四、最小堆(优先队列)五、时间轮(环形队列+双向链表)五、红黑树(std::set自动排序)

一、timerfd

调用timerfd_create()创建一个时间文件描述符即把时间变为文件描述符,定时器超时则文件描述符会变得可读,这样可以和epoll结合起来,统一处理I/O事件和超时事件。可以把timerfd和时间戳一起作为key,避免两个定时器相同的情况。

二、定时器的概念

网络编程中应用层的定时器是很有必要的,这可以让服务端主动关闭时间很久的非活跃连接。另外一种解决方案是TCP的keepalive,但它只能检测真正的死连接,即客端主机断电,或者网线被拔掉这种情况。如果客端连接上,但什么都不做,keepalive是毫无办法的,它只能一定时间后不断的向客户端发送心跳包。

在开发高性能服务器中,定时器总是不可或缺的, 常见的定时器实现三种,分别是:排序链表,最小堆,时间轮。

三、排序链表

升序定时器链表(使用双向链表)将定时器按照超时时间做升序排序,心博函数从头结点开始一次处理每个定时器,直到遇到一个尚未到期的定时器,然后调用定时器超时回调函数,以执行定时任务。

这种定时器设计的缺点在于,添加一个定时器的复杂度是O(n),因为要保持有序性,所以需要遍历链表插入到合适的位置。假设系统有大量的定时器(10W个)使用升序链表型的就会有性能问题。

四、最小堆(优先队列)

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左子节点和右子节点的值。

由于堆是一种经过排序的完全二叉树,因此在构建的时候需要对新插入的节点进行一些操作以使其符合堆的性质。这种操作就是节点的上浮与下沉。

由于定时器的触发是由于时间到了,因此只有时间最短的定时器会首先被触发,通过这个原理,我们可以采用最小堆,将按时间顺序排序,堆顶元素是时间最短的定时器,因此只要判断堆顶元素是否被触发即可。只有堆顶定时器的时间到了,才会到其他时间较晚的定时器的时间。 【特点】:

最小堆一般是采用堆的方式实现,元素访问速度远高于采用链表方式的红黑树,插入性能快红黑树好几倍,但最小堆的删除性能并不快于红黑树;最小堆的最大缺点就在于必须是连续的内存。

五、时间轮(环形队列+双向链表)

时间轮简介:时间轮方案将现实生活中的时钟概念引入到软件设计中,主要思路是定义一个时钟周期和步长(比如时钟的一秒走一次),当指针每走一步的时候,会获取当前时钟刻度上挂载的任务并执行: 以上图为例,假设一个格子为1秒,整个一圈表示的时间为12秒,此时需要添加5秒后执行的任务,则此时改任务一个放到第(1+5=6)的格子内,如果此时添加13秒后执行任务,此时该任务应该等转完一圈后round为1 放到第二格子中,指针每转动一个一格,获取当前round为0的任务执行,格子上的其他任务round减1 。问题:当时间跨度很大,数量很大时,单层的时间轮造成的round很大,一个格子中链很长,所以衍生出多级时间轮的设计方案 。 假设图中每层轮子为20个格子,第一层轮子最小时间间隔为1ms,第二层为20ms,第三层为400ms,此时添加5ms后执行的任务,此时应该添加到第一层的第5格子中。如果此时添加445ms后执行的任务,则第一层表示的时间跨度不够,第二层表示的时间跨度也不够,第三层表示的时间跨度足够,该任务应该放到第三层轮子第二格子中,该轮子指针指到第二格子中时,计算离任务启动时间还有多长时间,慢慢将该任务移动到底层轮子上,最终任务到期执行。

【特点】:

是任务的添加与移除,都是O(1)级的复杂度;不会占用大量的资源;只需要有一个线程去推进时间轮就可以工作了。

五、红黑树(std::set自动排序)

Nginx定时器实现的核心是使用一棵红黑树来存储各个定时事件,每次循环的时候就从这棵树里找出超时的事件,然后一一触发,完成定时任务操作。 在worker进程的每一次循环中都会调用ngx_process_events_and_timers函数,在该函数中就会调用处理定时器的函数ngx_event_expire_timers,每次该函数都不断的从红黑树中取出时间值最小的,查看他们是否已经超时,然后执行他们的函数,直到取出的节点的时间没有超时为止。

红黑树插入是最坏情况要比较2logN次(最高的高度)外加不超过两次旋转,最小堆最坏情况是logN次;红黑树删除不需要比较只需要不超过3旋转,查找最小值需要遍历logN。

参考: https://blog.csdn.net/FreeeLinux/article/details/54884771 https://blog.csdn.net/u010939285/article/details/80049412

相关推荐

C9 - 英雄联盟WIKI 365娱乐游戏

C9 - 英雄联盟WIKI

📅 06-29 👁️ 5473
2022 年改变头发颜色的 8 款最佳应用 365娱乐游戏

2022 年改变头发颜色的 8 款最佳应用

📅 06-28 👁️ 4762
城市学研究信息2024年第9期(总第1603期) 365bet足球信誉开户

城市学研究信息2024年第9期(总第1603期)

📅 06-27 👁️ 7793