ZLMediaKit/ZLToolKit

Is there a defect in the Timer implementation?

wanglxchina opened this issue · 7 comments

问题:
Timer的实现未考虑执行回调本身的耗时,比如一个定时任务1秒执行一次,一次执行耗时500毫秒,按照现有的逻辑实际执行间隔会变为1000 + 500 = 1500毫秒的执行间隔;
修改方案:
统计实际执行回调耗时,下次doDelayTask减去本次耗时时长,如果回调耗时超过定时时长,则下次立即执行~

这样实现太复杂,即便加上 delay 也无法保证精度。有哪些场景是必须在指定的时刻执行的呢?

并非指定时刻执行,是每隔N秒执行固定任务,比如固定间隔的心跳等等;实现并不复杂,一种方法是上面说的统计耗时,在实现中减去耗时,另外一种方法是记录timestamp,每次epoll_wait时用now - timestamp

在timer中执行耗时任务 本身就不符合异步非阻塞编程的规范 我们假定所有任务都是异步的作为设计前提
轻微的执行延时 并不会对精度影响太大。
实际上 对延时非常敏感 要求到毫秒级别的定时任务非常少见 而且非实时操作系统内核也无法保障调度的实时性
也可能由于调度不及时导致精度不够 我觉得 为了考虑这个增加这些逻辑并不划算

而且 zltoolkit保障任务之间的执行延时 也并不能算是bug,如果一个任务偶尔执行延时是300ms 但是它设置的间隔是500ms
按照你的设定 也就是下次执行应该在200ms以后 但是这是否真的是用户预期的呢? 我觉得未必吧?

以异步任务作为设计的前提是有道理的,但是作为基础类库来说行为跟预期并不一致,从定时器概念理解1秒执行一次就是1秒一次(当然可以有误差),否则就不是定时器;举例来说,利用这个定时器进行视频编码控制为60fps,如果忽略编码本身的耗时,实际编码帧率就会偏差很多 ;当然我说的这些都是从基础类库供别人使用为前提哈,不能揣测调用者的意图,概念需要清晰

另外可以参考下Linux系统timerfd的逻辑哈,它的行为跟我期望的是一致的~