目录
背景:
问题分析:
使用APE工具,查看录制的原始门信号是否存在异常
查看报文读取是否存在问题
分析报文读取代码
为什么在Windows系统中,解析后的门信号没有存在跳变情况
是否Windows 和Linux下 unordered_map中数据先后位置不一致
验证在相同输入下,在不同操作系统下,存储到队列中数据是否一致,在相同系统下,队列中数据存储是否一致
结论:
容器介绍:
unordered_map:
map:
性能对比:
100w量级的耗时:
参考资料:
背景:
最近在开发一个从文件中解析CAN信号功能时,在Ubuntu系统中发现门信号的状态存在跳变情况,而在Windows系统中,门信号的状态正常。
问题分析:
-
使用APE工具,查看录制的原始门信号是否存在异常
有图可知,原始信号正常,而解析的门信号存在跳变。
-
查看报文读取是否存在问题
通过分析,发现从文件中解析出来的can报文就存在跳变情况。
-
分析报文读取代码
通过分析,发现在两个虚拟通道组中,存在相同的CAN 报文ID ,虚拟通道组分别为35和113。其中35通道组为CAN1通道为DBC文件中报文数据,而113通道组为CAN2通道,不在DBC文件中。
在进行CAN报文解析时,首先是按照虚拟通道组逐个进行解析,并且按照虚拟通道号为key值进行存储到unordered_map中。
在所有虚拟通道组解析完后,将CAN报文数据存储到以CAN ID为key值的unordered_map中。
当存在相同的CAN ID时,就会存在CAN 数据被覆盖的情况。
因此,是由于存在相同CAN ID,导致解析后报文数据别另一个CAN报文内容覆盖的情况,导致信号存在跳变。
-
为什么在Windows系统中,解析后的门信号没有存在跳变情况
通过分析,CAN报文从虚拟通道组解析后,存储到unordered_map中,由于unordered_map是无序,因此对于虚拟通道组35和113 是随机存储,先后顺序不固定,因此哪个通道组存储在另一个通道后,最后输出的报文就时该报文。
-
是否Windows 和Linux下 unordered_map中数据先后位置不一致
通过分析,发现Windows和Linux下,unordered_map中key值存储先后顺序不一致.
在Linux下,查看队列存储顺序:
因此,在Linux系统中,实际输出报文内容为113通道数据。(键值转换关系uint32_t id = (i + 1)*10 + channelNumber; i为虚拟通道号,channelNumber为1)
在Windows下,查看队列顺序:
在Windows下,实际输出报文内容为35通道数据,因此,在Windows下,门信号不存在跳变情况。
-
验证在相同输入下,在不同操作系统下,存储到队列中数据是否一致,在相同系统下,队列中数据存储是否一致
使用同一段代码进行测试,分别验证以上两个问题:
#include <iostream>
#include <unordered_map>
#include <iostream>
int main()
{
std::unordered_map<uint32_t, uint32_t> map1;
std::unordered_map<uint32_t, uint32_t> map2;
for(uint32_t i = 0; i < 10; i++)
{
map1[i] = i;
map2[i] = i;
}
std::cout << "map 1 : " << std::endl;
std::unordered_map<uint32_t, uint32_t>::const_iterator iter = map1.begin();
while (iter != map1.end()) {
std::cout << " " << iter->first;
iter++;
}
std::cout << std::endl;
std::cout << "map 2 : " << std::endl;
iter = map2.begin();
while (iter != map2.end()) {
std::cout << " " << iter->first;
iter++;
}
std::cout << std::endl;
}
在Linux系统上输出:
在Windows系统上输出:
因此可得:对于unordered_map队列,相同输入情况下,在同一操作系统下,存储key值顺序是一致的,在不同操作系统下,存储的key值顺序是不一致的。
结论:
- 由于unordered_map队列是无效的,并且在不同操作系统下,内部存储key值顺序是不确定的。
- 对于不同通道的CAN ID,需要开辟不同存储空间进行存储,当存在相同CAN ID 时避免出现报文覆盖的情况。
容器介绍:
unordered_map:
- unordered_map是一个无序容器,它基于哈希表(Hash Table)实现。它使用键的哈希值来存储和访问元素,因此在`unordered_map`中插入和查找元素的时间复杂度通常为O(1),具有常数时间复杂度的特点。然而,由于哈希表的实现方式,`unordered_map`的元素顺序是不确定的。
map:
- map是一个有序容器,它基于红黑树(Red-Black Tree)实现。它以键值对的形式存储数据,并根据键的排序对元素进行排序。这意味着在`map`中插入和查找元素的时间复杂度为O(log n),其中n是容器中的元素数量。由于有序性质,`map`可以高效地进行范围查询和有序遍历。
对于需要存储为有序队列使用map,对于无顺序要求存储,只用unordered_map。由于unordered_map的无效性,对于同样输入顺序,在不同系统上,在内存中存储的顺序是不同的。
性能对比:
100w量级的耗时:
map insert time: 840.515000 ms
map find time: 764.570000 ms
map erase time: 753.324000 ms
unordered_map insert time: 488.741000 ms
unordered_map find time: 228.738000 ms
unordered_map erase time: 255.590000 ms
参考资料:
C++中的unordered_map用法详解-CSDN博客
安全验证 - 知乎