版权声明:本文为本文为博主原创文章,转载请注明出处。如有问题,欢迎指正。博客地址:https://www.cnblogs.com/wsg1100/
可能大部分人一直好奇VxWorks与xenomai对比,实时性孰优孰劣,正好笔者最近要做一个这方面的对比。声明:下面数据,仅供个人参考,有不对的地方还请指出。
本文继上一篇文章【原创】xenomai与VxWorks实时性对比(Jitter对比),主要对比VxWorks与xenomai两个硬实时操作系统在对各类资源操作时,任务抢占切换的耗时。
一、环境
简单介绍一下环境:
硬件平台:双核cortex-A15处理器,CPU频率1.5GHZ,内存2GB。
xenomai:Linux-4.19+xenomai 3.1,具体配置:略;
VxWorks:VxWorks 7,具体配置:略;
注:
- 由于VxWorks benchmark测试包含很多测试项,以下数据为其中包含的几项,每项测试2万次;xenomai与其一致。
- 既然对比,那么测试方法、数据处理就得和VxWorks一致,所以xenomai测试用例实现参考VxWorks benchmark测试用例。
- xenomai的数据为用户态测试,VxWorks数据为内核态测试,测试本身xenomai就处于劣势,哈哈,有兴趣的小伙伴可以将测试用例在xenomai内核态写一份看看。
- xenomai测试用例使用Alchemy API编写,Alchemy API是一层posix接口的封装,所以Alchemy API性能可能弱于POSIX接口。
二、 指标概念
任务切换时间(task switching time),定义为系统在两个独立的、处于就绪态并且具有相同优先级的任务之间切换所需要的时间。
切换所需的时间主要取决于保存任务上下文所用的数据结构以及操作系统采用的调度算法的效率。产生任务切换的原因可以是资源可得,信号量的获取等。任务切换是任一多任务系统中基本效率的测量点,它是同步的,非抢占的。影响任务切换的因素有:主机CPU的结构,指令集以及CPU特性等
2.1 单核CPU
即测试相关的任务运行在同一CPU核上,这里表示单核上的上下文切换。
2.1.1 信号量响应上下文切换时间
信号量响应时间是指从一个任务释放信号量到另一个等待该信号量的任务被激活的时间延迟。 在RTOS中,通常有许多任务同时竞争某一共享资源,基于信号量的互斥访问保证了任一时刻只有一个任务能够访问公共资源。信号量响应时间反映了与互斥有关的时间开销,因此也是衡量RTOS实时性能的一个重要指标。
- bmCtxSempend
① 创建两个任务:高优先级任务$Task1$ 和 优先级任务$Task2$;
②$Task1$先非阻塞获取信号量,确保信号量为空。
③$Task1$记录当前时间T1,再次获取信号量导致挂起;
④ 上下文切换到低优先级任务$Task2$运行,$Task2$读取时间T2,再释放信号量;
⑤$Task1$得到信号量恢复运行。计算切换时间$T = T2 - T1$,反复进行②~⑤操作。
⑥最终统计最大值、最小值、平均值。
- bmCtxSemunpend
① 创建两个任务:高优先级任务$Task1$ 和 优先级任务$Task2$;
②$Task1$获取信号量导致挂起;
③上下文切换到低优先级任务$Task2$运行,$Task2$读取时间$T_1$,再释放信号量;
④ 高优先级$Task1$得到信号量恢复运行,读取时间$T_2$。进入下一次循环,反复进行②~⑤操作。
⑤ 最终统计最大值、最小值、平均值。
2.1.2 消息队列响应上下文切换时间
与信号量响应时间类似,是指从一个任务发送消息队列到另一个等待该消息队列的任务被激活的时间延迟。
- bmCtxMsgQPend
① 创建两个任务:高优先级任务$Task1$ 和 优先级任务$Task2$;
② $Task1$记录当前时间T1,获取读取消息队列导致阻塞挂起;
③ 上下文切换到低优先级任务$Task2$运行,$Task2$读取时间T2,再向消息队列发送Byte数据,发送后阻塞;
④ $Task1$消息可用恢复运行。计算切换时间$T = T2 - T1$,反复进行②~⑤操作。
⑤ 最终统计最大值、最小值、平均值。
- bmCtxMsgQunPend
① 创建两个任务:高优先级任务$Task1$ 和 优先级任务$Task2$;
②$Task1$接收消息导致挂起;
③上下文切换到低优先级任务$Task2$运行,$Task2$读取时间T1,发送1Byte消息;
④ 高优先级$Task1$消息可用恢复运行,读取时间T2。进入下一次循环,反复进行②~⑤操作。
⑤ 最终统计最大值、最小值、平均值。
2.1.3 事件响应上下文切换时间
也就是对于event操作的上下文切换,与上面两种类似不再说明。
2.1.4 任务上下文切换时间
以上测试中,在资源上任务切换,下面是单纯的优先级调度下的任务切换。
需要注意的是:VxWorks中priority数值越高,优先级越低,xenomai相反。
① 优先级为50的任务$Task1$ 创建更高优先级40的任务$Task2$;
② $Task2$创建后立即抢占,$Task2$运行后立即降低自身优先级为60,比$Task1$优先级低
③$Task1$此时为最高优先级得到运行,读取时间T1,提升$Task2$优先级为40;
④ $Task2$此时为最高优先级抢占运行,发生一次上下文切换;
⑤ $Task2$运行后立即降低自身优先级为60;
⑥$Task1$此时为最高优先级得到运行,发生一次上下文切换;
测试时间$T=T_2-T_1$,包含了1次提升优先级操作耗时$T_r$、1次降低优先级操作耗时$T_l$、2次任务切换$T_{sw}$、2次读取时间戳耗时$T_{rt}$。所以上下文切换时间$T_{sw}=\frac{T-T_r-T_l-2T_{rt}}{2}$。
2.1 SMP
实时任务分别运行在不同CPU上,其任务切换在上述的基础上,还包含了多核间IPI 通信(Interrupt-Procecesorr Interrupt处理器间的中断)耗时。
以bmCtxSemunpend示例如下,其余的类似不再赘述。
三、 结果对比
3.1 单核
Vxworks | avg | min | max |
---|---|---|---|
bmCtxSemPend | 1.387 | 0.162 | 5.205 |
bmCtxSemUnpend | 1.389 | 0.162 | 5.205 |
bmCtxMsgQPend | 1.719 | 0.325 | 6.181 |
bmCtxMsgQUnpend | 2.183 | 0.487 | 7.807 |
bmCtxEventPend | 1.349 | 0.000 | 5.042 |
bmCtxEventUnpend | 1.466 | 0.162 | 5.367 |
bmCtxTaskSwitch | 0.975 | 0.000 | 4.635 |
Xenomai | avg | min | max |
---|---|---|---|
bmCtxSemPend | 3.597 | 3.252 | 6.345 |
bmCtxSemUnpend | 3.735 | 3.415 | 7.482 |
bmCtxMsgQPend | 4.228 | 3.903 | 6.833 |
bmCtxMsgQUnpend | 5.368 | 5.042 | 8.622 |
bmCtxEventPend | - | - | - |
bmCtxEventUnpend | - | - | - |
bmCtxTaskSwitch | 8.365 | 0.326 | 63.522 |
可以看到xenomaibmCtxTaskSwitch
数据比较差,为什么什么会这样呢?VxWorks测试程序与内核都处于内核态(同一地址空间),而xenomai测试则是在用户态测试,可以回到2.1.4小节,其中$T=T_2-T_1$这段时间内的每一个操作都是必须发起实时系统调用来完成的,其中修改优先级还涉及Linux线程部分,除此之外由于系统调用路径复杂,每个系统调用时间不是确定的,比如前后两次修改优先级操作的时间是不等的,这就造成计算出的$T_{sw}$失真。通俗的说这个测试方法不适合xenomai用户态,将该测试放到xenomai内核态才与VxWorks具有可比性。
另外,本测试基于xenomai 3.1。xenomai任务对event资源不会发生阻塞唤醒(非抢占)了,xenomai3.0.8不存在这个问题,所以这两项没有测试数据。有兴趣的小伙伴可以研究一下,顺便还能向社区提个issue或patch,呵呵~~。
3.2 SMP
VxWorks没有启用SMP,所以这部分没有VxWorks的数据,只有xenomai的。
Xenomai | avg | min | max |
---|---|---|---|
CtxSmpAffinitySemUnPend | 3.826 | 3.578 | 8.296 |
CtxSmpAffinityMsgQUnPend | 5.262 | 4.879 | 8.133 |
CtxSmpNoAffinitySemUnPend | 3.766 | 3.415 | 6.181 |
CtxSmpNoAffinityMsgQUnPend | 5.322 | 5.042 | 9.597 |