std :: map(和family)查找性能问题

时间:2016-09-29 08:44:59

标签: c++ c++11 dictionary stdmap bit-fields

我正在编写一个位域抽象类,它包含一个32位内存(u32 = unsigned int),并提供对该内存中各个位或范围的访问。

为了实现这一点,我使用了一个std :: map,其中唯一键是指针(不是std :: string)到表示助记符的C字符数组,值是包含位域属性的结构(例如助记符,起始位置,长度,初始值和字段值)。所有这些属性都是常量并且在启动时定义,除了仅在更改基础u32值时更改的字段值。 (另请注意:我刚刚将助记符指针值重用为唯一键)。

这在模拟器中使用,其中返回位域值(只读)的getBitfieldValue()每秒被调用多次。

在VS 2015更新3下编译和分析代码时(使用-O2和我能找到的任何速度优化),它显示getBitfieldValue()函数和扩展名std::find()正在占用总CPU时间的60-70%......太慢了。

我尝试过使用其他地图实现,例如Boost::flat_mapgoogle::dense_hash_mapstd::unordered_map,但它们有些帮助但最终仍然太慢(~50-60%)。

我的猜测是我正在使用地图用于错误的目的,但我不确定是否只有5-20位域映射(小查找大小)......它看起来似乎太慢了。大部分时间都花在寻找相同的领域。

可在此处找到相关的类源代码:BitfieldMap32

启动时如何初始化地图的示例(仅限一次运行):

struct Fields
{
    static constexpr char * ADDR = "ADDR";
    static constexpr char * SPR = "SPR";
};
ExampleClass() // constructor
{
    // registerField(mnemonic, start position, length, initial value)
    registerField(Fields::ADDR, 0, 31, 0);
    registerField(Fields::SPR, 31, 1, 0);
}

如何访问字段值(只读):

// getFieldValue definition.
const u32 & BitfieldMap32_t::getFieldValue(const char* fieldName)
{
    return mFieldMap.find(fieldName)->second.mFieldValue;
}

// Field access.
const u32 value = ExampleClassPointer->getFieldValue(Fields::ADDR)

有关如何缩短查找时间的任何想法?或者我是否需要一起更改实施?

1 个答案:

答案 0 :(得分:4)

IIUC,使用字典(std::mapstd::unordered_map)是一个巨大的矫枉过正。也许您应该使用以下内容:

  1. 该类应该只是一个整数内部存储(或最多std::bitset)的包装器。

  2. 助记符应为enum s,而不是std::string s。

  3. 在内部,std::vector有效地将每个enum值映射到bitmask。 (如果您使用的是c ++ 11 enum,请参阅here如何将enum值转换为std::vector内的位置。

    < / LI>
  4. 每个操作都应该使用助记符,通过索引查找位掩码,并将其应用于内部存储。