Skip to content

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

@ktprime

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];
};


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