ZLMediaKit / ZLToolKit

一个基于C++11的轻量级网络框架,基于线程池技术可以实现大并发网络IO
MIT License
1.94k stars 581 forks source link

Is there a defect in the Timer implementation? #185

Open wanglxchina opened 11 months ago

wanglxchina commented 11 months ago

Issue:

The implementation of Timer does not consider the time spent executing the callback itself. For example, if a timed task is scheduled to execute every 1 second, and each execution takes 500 milliseconds, the actual execution interval will become 1000 + 500 = 1500 milliseconds according to the current logic.

Solution:

Statistically track the actual time spent executing the callback. In the next doDelayTask, subtract the time spent in the current execution. If the callback execution time exceeds the scheduled interval, execute the task immediately next time.

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

TRANS_BY_GITHUB_AI_ASSISTANT

wasphin commented 11 months ago

This implementation is too complex, and even with a delay, accuracy cannot be guaranteed. What are the scenarios where execution at a specific time is absolutely necessary?

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

TRANS_BY_GITHUB_AI_ASSISTANT

wanglxchina commented 11 months ago

It is not executed at a specific time, but rather executes a fixed task every N seconds, such as a fixed interval heartbeat; the implementation is not complicated, one method is to count the time as mentioned above, and subtract the time in the implementation, another method is to record the timestamp, and use now - timestamp each time epoll_wait is called.

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

TRANS_BY_GITHUB_AI_ASSISTANT

wanglxchina commented 11 months ago

You can refer to the implementation: https://github.com/chenshuo/muduo/blob/master/muduo/net/TimerQueue.cc

可以参考实现:https://github.com/chenshuo/muduo/blob/master/muduo/net/TimerQueue.cc

TRANS_BY_GITHUB_AI_ASSISTANT

xia-chu commented 11 months ago

Executing time-consuming tasks in a timer itself does not conform to the specifications of asynchronous non-blocking programming. We assume that all tasks are asynchronous as a design premise.

Slight execution delays will not have a significant impact on accuracy.

In practice, timer tasks that are very sensitive to delays and require millisecond-level accuracy are very rare. Moreover, non-real-time operating system kernels cannot guarantee real-time scheduling.

It is also possible that the accuracy is not sufficient due to untimely scheduling. I think it is not worthwhile to consider adding these logic for this reason.

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

TRANS_BY_GITHUB_AI_ASSISTANT

xia-chu commented 11 months ago

Moreover, zltoolkit guarantees the execution delay between tasks, which cannot be considered a bug. If a task occasionally experiences a delay of 300ms, but its interval is set to 500ms, according to your settings, the next execution should be in 200ms. However, is this really what the user expects? I don't think so.

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

TRANS_BY_GITHUB_AI_ASSISTANT

wanglxchina commented 11 months ago

It makes sense to design with asynchronous tasks as a premise, but as a basic library, the behavior is not consistent with expectations. From the concept of a timer, understanding that executing once every second means once every second (of course, there may be errors), otherwise it is not a timer; for example, using this timer to control video encoding to 60fps, if the encoding time itself is ignored, the actual encoding frame rate will deviate a lot; of course, what I am saying is based on the premise that the basic library is used by others, and the caller's intention cannot be guessed, the concept needs to be clear.

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

TRANS_BY_GITHUB_AI_ASSISTANT

wanglxchina commented 11 months ago

You can also refer to the logic of the timerfd in the Linux system, its behavior is consistent with what I expect. ~

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

TRANS_BY_GITHUB_AI_ASSISTANT