[Apollo Cyber RT] Timer实现

news2025/1/11 7:01:59

Timer的实现方式

Timer有多种实现方式,CyberRT采用了时间轮(TimingWheel)方式。关于Timing Wheels的详细描述可以参考附录的链接。此处不赘述。

CyberRT Timer的类构成

在这里插入图片描述

实现细节

Timer

Timer类是门户,但定时器真正的核心是TimingWheel。
Timer的定义相对简单,基本就是传入period(多久后触发)、callback(触发后执行的函数)、oneshot(执行一次,还是循环执行)创建定时器,然后调用Start()启动定时器。调用Stop()停止定时器。

测试样例可以再Timer_test.cc中找到。
在这里插入图片描述
Timer的调用Start()后,会调用InitTimerTask()创建一个新的TimerTask, 然后通过timing_wheel_->AddTask(task_)添加到时间轮对应的slot上。

TimerTask指针是时间轮调度操作的单元。Timer::InitTimerTask()函数较长,主要是对循环调用场景下task_->callback的Lambda定义。

在这里插入图片描述
在这里插入图片描述
对于循环场景,我们需要下一次调度的准确时间,所以我们需要计算函数的执行时间execute_time_ms和累积的错误时间accumulated_error_ms。

函数执行消耗时间execute_time_ms比较容易理解, 累积的错误时间accumulated_error_ms第一次看到时,容易让人疑惑。下面用一个简单的例子来解释一下。

假设定时器tick为2ms。一个循环执行的timer,每11ms执行一次。所以第一次会向上取整,落到第12ms这个tick上。到时触发后,执行耗时2ms,此时当前tick为第14ms这个tick。

我们准备重新将timer加入到定时器中,下一次执行时间该是多少呢?如果没有accumulated_error_ms,我们会计算得到 11 - 2 = 9, 使用当前时间14 + 9 = 23,向上取整的到了24。也就是说下一次会在第24ms时触发。这和我们理想情况下第二次22ms触发整整差了2ms。如果没有accumulated_error_ms,越往后累积偏差越大,这样精确性就得不到保障了。

下面我们看下考虑到accumulated_error_ms后的情况。我们通过

accumulated_error_ms += start(当前时刻) - last_execute_time_ms(执行耗时) - interval_ms = 14 - 2 - 11 = 1

的到了accumulated_error_ms=1,在随后的计算中

next_fire_duration_ms= interval_ms-execute_time_ms-accumulated_error_ms= 11 - 2 - 1 = 8

的到了下一次触发间隔时间next_fire_duration_ms=8
也就是说在14(当前时刻)+ 8 = 22ms时触发,这和我们期望的时间完全一致,时间精确性的到了最大限度地保障。

在这里插入图片描述

TimingWheel

CyberRT使用了两个时间轮,一个主时间轮和一个辅助时间轮。
主时间轮512个slot,tick为2ms,可以承载1024ms。
副时间轮64个slot,一个slot对应1024ms。当主时间轮运行一周后,会从副时间轮对应slot中取出task(时间范围1024ms)应用到主时间轮上,继续执行。

所以可以设置的最大间隔为 TIMER_MAX_INTERVAL_MS = 65536ms,约为65秒。

static const uint64_t WORK_WHEEL_SIZE = 512;
static const uint64_t ASSISTANT_WHEEL_SIZE = 64;
static const uint64_t TIMER_RESOLUTION_MS = 2;
static const uint64_t TIMER_MAX_INTERVAL_MS =
    WORK_WHEEL_SIZE * ASSISTANT_WHEEL_SIZE * TIMER_RESOLUTION_MS;  //65536,约65s左右。

  TimerBucket work_wheel_[WORK_WHEEL_SIZE];           //主时间轮
  TimerBucket assistant_wheel_[ASSISTANT_WHEEL_SIZE]; //辅助时间轮

Timer主线程

主线程运行TickFunc函数,代码如下:

  1. Tick()函数是执行当前slot中到期的所有TimerTask。
  2. rate.Sleep() 负责精确休眠tick时间,即2ms。
  3. 更新时间轮index
  4. 如果时间轮走过一圈,则调用Cascade()从辅助时间轮中取对应slot的TimerTask部署到主时间轮上。
    在这里插入图片描述

AddTask函数

AddTask根据current_work_wheel_index + next_fire_duration_ms/TIMER_RESOLUTION_MS 得到对应的时间轮index。

  1. 如果index 没有超过WORK_WHEEL_SIZE,则直接插入到对应slot。
    在这里插入图片描述

  2. 如果index超过WORK_WHEEL_SIZE,但是assistant_ticks为1并且index小于当前时间的index。
    在这里插入图片描述

  3. assistant_ticks为1且work index>= current index或者assistant_ticks > 1
    示例:assistant_ticks=2,直接将任务插入到当前assistant wheel index + 2的slot中。
    在这里插入图片描述
    在这里插入图片描述

附录

Timing Wheels

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/21495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

索引的基础使用

索引: 分类: 功能逻辑:普通索引、唯一索引、主键索引、全文索引物理实现方式:聚簇索引,非聚簇索引作用字段个数:单列索引,联合索引 索引创建: --主键索引 CREATE TABLE dept( de…

SpringBoot的使用

一、Maven的环境搭建 暂时未完成.... 二、创建项目 创建完以后的目录如下&#xff1a; 然后配置pom.xml 再放入配置项 <!-- 2 我的依赖仓库源 , 首先配置仓库的服务器位置,首选阿里云&#xff0c;也可以配置镜像方式&#xff0c;效果雷同 --><repositories><re…

章节四:RASA 训练数据介绍

一、前言 一般来说&#xff0c;机器人可以跟人对话&#xff0c;机器人说什么是最难的&#xff0c;顶多是人工编写几种规则和模版来回复即可。但是要让机器人理解人的意图&#xff0c;确实非常难的事情。因为语言具有多样性&#xff0c;多义词&#xff0c;一语双关&#xff0c;…

872. 最大公约数(史上最详细讲解 7种算法,STL+算法标准实现)

一&#xff0c;什么是最大公约数 最大公约数&#xff08;Greatest Common Divisor&#xff09;指两个或多个整数共有约数中最大的一个。也称最大公因数、最大公因子&#xff0c;a&#xff0c; b的最大公约数记为&#xff08;a&#xff0c;b&#xff09;&#xff0c;同样的&…

测试架构工程师需要具备哪些能力 ?

目录 前言 为什么软件项目需要架构设计&#xff1f; 测试架构师需要解决什么问题&#xff1f; 测试架构师需要具备哪些能力&#xff1f; 测试工程师如何培养架构能力&#xff1f; 总结 重点&#xff1a;配套学习资料和视频教学 前言 相比于我们常见的研发架构师&#xf…

深入ftrace kprobe原理解析

Linux krpobe调试技术是内核开发者专门为了编译跟踪内核函数执行状态所涉及的一种轻量级内核调试技术&#xff0c;利用kprobe技术&#xff0c;内核开发人员可以在内核的绝大多数指定函数中动态插入探测点来收集所需的调试状态信息而基本不影响内核原有的执行流程。本章的是基于…

Spring-Mybatis整合 | 原理分析

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 文章目录▌环境搭建▌Mybatis流程回顾▌Mybatis-Spring整合SqlSessionTemplate方式SqlSessionTemplate分析configLocation & mapperLocations分析SqlSessionDaoSu…

ERD Online 4.0.3数据库在线建模(免费、更美、更稳定)

ERD Online 4.0.3❝ 全新升级&#xff0c;团队功能、权限管理、更美更稳定从这个版本&#xff0c;我们隆重推出低代码设计平台LOCO&#xff0c;见下文❞发展里程碑 4.0.3改动一览 功能完善 个人项目 个人项目即原有的项目管理&#xff0c;每个账号只能编辑自己的「个人项目」。…

linux下自动构建工具make:makefile

文章目录make/makefile介绍makefile的核心规则makefile的寻找规则makefile的伪目标什么是makefile&#xff1f;大多数人都应该是不太清楚的&#xff0c;因为现在人们基本都用着非常好的适合自己的IDE&#xff0c;而IDE为人们做了makefile该做的&#xff0c;从而导致大多数人并不…

同花顺_代码解析_技术指标_O

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 OBOS OBV OBVFS OI指标 OSC OBOS 超买超卖指标 大盘指标。 输出超买超卖指标:上涨家数-下跌家数的N日异同移动平均 输出MAOBOS:OBOS的M日简单移动平均 1.指标上升至80时为超买&…

第2章 数据结构中栈与队列的概念

文章目录文档配套视频讲解链接地址第02 章 栈与队列2.1 栈与队列的框图2.2 栈1. 栈的概念2. 顺序栈3. 实例11 顺序栈4. 实例12 链式栈2.3 队列1. 队列的概念2. 顺序队列3. 实例13 顺序队列4. 链式队列5. 实例14 链式队列2.4 实例15 球钟问题2.5 队列与栈的转换1. 实例16 顺序的…

基于Labview的图像傅里叶变换研究-含Labview程序

⭕⭕ 目 录 ⭕⭕一、说明二、基于Labview的图像傅里叶变换研究三、Labview源程序下载一、说明 订阅该专栏后&#xff0c;可获取该专栏内的任意一份代码&#xff0c;请及时私信博主获取下载链接。 从该专栏获取的程序&#xff0c;博主有责任并将保证该程序能在您电脑上完整运行…

初识Spring框架~控制反转IoC、依赖注入DI以及Spring项目的创建方式

目录 Spring框架初识 Spring IoC IoC(控制反转) DI(依赖注入) Spring项目的创建 创建一个maven项目 配置XML文件 添加启动类 简单了解Bean对象的存储与获取 创建一个Spring IoC容器 注册Bean对象 获取并使用Bean对象 Spring框架初识 通常所说的Spring是指Spri…

java知识梳理 第十五章 I/O流

一、文件 1.1 文件流 值得一提的是&#xff0c;这里的流的概念是围绕java程序展开的 1.2 常用的文件操作 1.2.1 创建文件对象相关构造器和方法 代码演示如上&#xff0c;读者可自行实验 1.2.2 获取文件的相关信息 代码演示如上&#xff0c;读者可自行实验 1.2.3 目录的操作和删…

NodeJs实战-待办列表(6)-前端绘制表格显示待办事项详情

NodeJs实战-待办列表6-前端绘制表格显示待办事项详情定义服务器返回的 json 数据前端绘制动态表格后端返回列表数据验证执行添加查看数据库中的数据是否与页面一致使用浏览器debug表格绘制过程项目地址前面几节显示的列表&#xff0c;看不到事项创建时间&#xff0c;完成时间&a…

springmvc-day03

springmvc-day03 第一章 拦截器 1.概念 1.1 使用场景 1.1.1 生活中坐地铁的场景 为了提高乘车效率&#xff0c;在乘客进入站台前统一检票&#xff1a; 1.1.2 程序中的校验登录场景 在程序中&#xff0c;使用拦截器在请求到达具体 handler 方法前&#xff0c;统一执行检…

基于stm32单片机的智能恒温自动加氧换水鱼缸

资料编号&#xff1a;105 下面是相关功能视频演示&#xff1a; 105-基于stm32单片机的智能恒温自动加氧换水鱼缸Proteus仿真&#xff08;源码仿真全套资料&#xff09;功能讲解&#xff1a;采用stm32单片机&#xff0c;ds18b20测量温度&#xff0c;LCD1602显示温度&#xff0c…

C语言第十一课(上):编写扫雷游戏(综合练习2)

目录 前言&#xff1a; 一、文件建立&#xff1a; 1.头文件game.h&#xff1a; 2.函数定义文件game.c&#xff1a; 3.工程测试文件test.c&#xff1a; 二、编写井字棋游戏&#xff1a; 1.程序整体执行思路&#xff1a; 2.menu菜单&#xff1a; 3.game游戏函数逻辑&#xff…

【Detectron2】代码库学习-5.标注格式- 矩形框, 旋转框,关键点, mask, 实例标注,IOU计算, 旋转框IOU计算,

文章目录Detectron2 内置的标注格式BoxMode 表示方式实用APIRotatedBoxesInstances 实例标注KeypointsMasks结语Detectron2 内置的标注格式 BoxesRotatedBoxesBitMasksPolygonMasksROIMasksKeypointsInstancesImageList BoxMode 表示方式 XYXY_ABSXYWH_ABSXYXY_REL # 相对模…

Windows安装mysql并且配置odbc

文章目录 mysql下载ODBC驱动下载安装mysql使用测试安装ODBC驱动添加ODBC数据源配置完成了用户不能远程访问的问题mysql下载 https://dev.mysql.com/downloads/installer/ ODBC驱动下载 https://dev.mysql.com/downloads/connector/odbc/ 安装mysql 点击mysql安装包,选择…