前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vppinfra --- Timer Wheels(时间轮)

vppinfra --- Timer Wheels(时间轮)

作者头像
dpdk-vpp源码解读
发布2023-03-07 17:01:36
7430
发布2023-03-07 17:01:36
举报
文章被收录于专栏:DPDK VPP源码分析DPDK VPP源码分析

Vppinfra支持可配置计时器的时间轮。可以在…/src/vppinfra/tw_timer_template.[ch]中查看源代码。以及…/src/vppinfra/tw_timer_xx.[ch]中定义的相当数量的模板实例。

关于时间轮的实现原理详细介绍可以参考文章:

https://blog.csdn.net/u013256816/article/details/80697456。是介绍kafka时间轮的实现。vpp 中实现细节时间轮也是一样的。这里不再讲解了。

tw_timer_template.h的实例化生成命名结构来实现特定的计时器时间轮。选择包括:计时器轮的数量(当前最多支持3个),每个时间轮的环槽的数量(必须是2的幂),以及每个“对象句柄”的计时器数量。

以tw_timer_2t_1w_2048sl.h模版为例子,时间轮的数量是1,时间轮的ring槽数量是2048,每个对象的句柄的占用的bit数量是2.通过make_internal_timer_handle函数可以了解到用户时间轮句柄user_handle是由2部分组成的。pool_index及timer_id。使用者需要注意。

代码语言:javascript
复制
#define TW_TIMER_WHEELS 1
    #define TW_SLOTS_PER_RING 2048
    #define TW_RING_SHIFT 11
    #define TW_RING_MASK (TW_SLOTS_PER_RING -1)
    #define TW_TIMERS_PER_OBJECT 2
    #define LOG2_TW_TIMERS_PER_OBJECT 1
    #define TW_SUFFIX _2t_1w_2048sl
    #define TW_FAST_WHEEL_BITMAP 0
    #define TW_TIMER_ALLOW_DUPLICATE_STOP 0

static inline u32
TW (make_internal_timer_handle) (u32 pool_index, u32 timer_id)
{
  u32 handle;
  ASSERT (timer_id < TW_TIMERS_PER_OBJECT);
#if LOG2_TW_TIMERS_PER_OBJECT > 0
  ASSERT (pool_index < (1 << (32 - LOG2_TW_TIMERS_PER_OBJECT)));
  handle = (timer_id << (32 - LOG2_TW_TIMERS_PER_OBJECT)) | (pool_index);
#else
  handle = pool_index;
#endif
  return handle;
}

时间轮使用实例:

我们可以查看vpp测试例子src/vppinfra/test_tw_timer.c来了解使用。

1、时间轮初始化

初始化一个间隔1s的的时间轮。每秒时间轮转一个槽位,最多支持2048s。timer interval也可以设置成0.1s,那么每秒ticks就是10。最多支持204.8s。

代码语言:javascript
复制
tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
              expired_timer_single_callback,
              1.0 / * timer interval * / );

2、添加计时任务

当前设置的最大支持expiration_time_in_u32_ticks 是2048s,超过就达不到准确计时器的作用,也可能存在异常。

代码语言:javascript
复制
handle = tw_timer_start_2t_1w_2048sl (&tm->single_wheel, elt_index,
                                   [0 | 1] / * timer id * / ,
                               expiration_time_in_u32_ticks);

3、删除计时任务

代码语言:javascript
复制
tw_timer_stop_2t_1w_2048sl (&tm->single_wheel, handle);

4、周期性调用查看是否过期事件。

代码语言:javascript
复制
 tw_timer_expire_timers_2t_1w_2048sl (tw, now)

5、计时时间到时,会调用回调处理函数

代码语言:javascript
复制
    static void
    expired_timer_single_callback (u32 * expired_timers)
    {
      int i;
        u32 pool_index, timer_id;
        tw_timer_test_elt_t *e;
        tw_timer_test_main_t *tm = &tw_timer_test_main;

        for (i = 0; i < vec_len (expired_timers);
            {
            pool_index = expired_timers[i] & 0x7FFFFFFF;
            timer_id = expired_timers[i] >> 31;

            ASSERT (timer_id == 1);

            e = pool_elt_at_index (tm->test_elts, pool_index);

            if (e->expected_to_expire != tm->single_wheel.current_tick)
              {
                fformat (stdout, "[%d] expired at %d not %d\n",
                         e - tm->test_elts, tm->single_wheel.current_tick,
                         e->expected_to_expire);
              }
         pool_put (tm->test_elts, e);
         }
     }

总结

简单介绍了时间轮的api,具体实现细节需要自己去阅读代码,实现逻辑并不复杂。时间轮的添加、删除、更新操作都是0(1)复杂度。在vpp主机协议栈及flowprope-plugins都有使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DPDK VPP源码分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档