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

std::map (and family) lookup performance issues

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

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

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

在 VS 2015 update 3 下编译和分析代码(使用 -O2 和我能找到的任何速度优化),它表明 getBitfieldValue() 函数,并且通过扩展 std::find() 正在采取大约占总时间的 60-70% cpu...太慢了。

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

我的猜测是我将映射用于错误的目的,但考虑到只有 5-20 个位域映射(小查找大小),我不确定...它似乎太慢了。大部分时间也会花在查找相同的字段上。

相关class源代码可以在这里找到: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)

关于如何减少查找时间有什么想法吗?还是我需要一起更改实现?

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

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

  2. 助记符应该是enums,不是std::strings。

  3. 在内部,有一个 std::vector 有效地将每个 enum 值映射到 bitmask. (If you're using c++11 enums, see here 如何将 enum 值转换到std::vector).

  4. 每个操作只需要取助记词,通过索引找到位掩码,并将其应用到内部存储。