-
Notifications
You must be signed in to change notification settings - Fork 44
Open
Description
在我的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
Labels
No labels