Skip to content

新的定时器 时间轮 + 4-dray heap #6

Description

@ktprime

在我的quic 网络库中,单个用户连接存在6-8个左右定时器(重传,延时发包,心跳,idle,ack, blackhole, send_flush ...),统计显示95%以上的操作删除和插入,真正触发非常少(活跃的ack和重传),每秒10w+次基本操作,需要超高性能的定时器毫秒精度设计方案。

上面各种方案或多或少存在应用场景限制,比如时间轮定时器存在如下缺陷
第一:存在空转现象,尤其是定时器不多,触发分布不均匀
第二:无法O(1)取到最小时间触发点 (比如网络库中 epoll 常用最小触发时间作为超时参数)
另外堆和红黑等实现中高频繁插入删除性能比较差 ,内存局部性性能不友好

我结合时间轮和4叉堆两种不同实现方案整合一直新的定时器, 基本能满足各种设计要求,
时间轮第一级(比如 256 毫秒内)用4叉堆实现。堆的大小至于太大,活跃的定时器基本都在堆中,
时间轮每256 ms更新一次堆中数据。


#pragma once

#include "util/heap_timer.h"
#include "util/wheel_timer.h"

// timer queue implemented with hashed hierarchical wheel + 4-dary heap.
// complexity:
//      AddTimer   CancelTimer   PerTick  GetMinTimer
//       O(1)       O(1)          O(1)            O(1)
//

class HWheelTimer : public TimerBase
{
public:
    HWheelTimer(int64_t now_time, uint32_t timer_size);

    timerId Schedule(int64_t deadline_ms, QTask* cb);
    bool Delay(int64_t deadline_ms, timerId timer_id);
    void Reset(int64_t deadline_ms, timerId timer_id, QTask* cb);

    bool Cancel(const timerId timer_id);
    bool Erase(const timerId timer_id);
    int Run(const int64_t now_ms);
    int64_t NearTime();
    int DumpTimer(char* buffer);

private:
    void tick();
    void add_wheel(TimerNode* node);
    bool cascade(int bucket);
    bool erase_node(TimerNode* node);
    bool erase_slot(WheelList& near, const TimerNode* node);

private:
    int64_t min_expire_;
    uint32_t addws_, addn1_, moves_, runs_, delays_;
#ifndef BIN_HEAP
    DaryHeap min_queue_;
#else
    BinHeap min_queue_;
#endif
    WheelList buckets_[WHEEL_BUCKETS][TVN_SIZE];
};


Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions