【问题标题】:Does MFC CMap have a good performance compared to std::unordered_map or std::map与 std::unordered_map 或 std::map 相比,MFC CMap 是否具有良好的性能
【发布时间】:2016-03-19 02:33:04
【问题描述】:

MFCCMapstd::unordered_mapstd::map性能好么,我问这个问题是因为我要在我公司开始一个项目,为了加快开发我要开始使用现有的“类似”项目,但在最后一个项目中,有 MFC CMap(哈希表映射),我认为使用 std::unordered_map 可能会提高性能。我在互联网上没有找到任何与CMap 相关的基准或好文章。 否则,对于std::unordered_map,我是否必须像在CMap 中那样修复哈希表的大小以避免冲突和性能问题?

【问题讨论】:

  • 我在网上没有找到任何与 CMap 相关的基准或好文章你为什么不自己用类似的数据集进行基准测试您将在生产中使用的硬件上使用什么?
  • CMap 没有移动支持(如果你想从函数中返回一个,你必须始终将它作为输出参数传递)并且不会在手表中显示任何有用的东西调试器中的窗口。您还必须编写 CMap<int, const int&, CString, const CString &> map; 之类的代码,而不是 std::unordered_map<int, const CString> map;。如果我是你,我什至不会考虑使用它——但这取决于你。
  • CMap 是一个过时的、不可携带的恐怖节目。帮我们一个忙:使用标准容器,帮助永远埋葬 MFC。
  • std::mapstd::unordered_map 之间选择新的 MFC 项目。我会远离所有 MFC 容器,除了 CString --- 另请参阅 std::map versus std::unordered_map
  • @Aminos 我理解这个问题,但是笨蛋软件经理需要接受教育,否则软件开发的纪律将被 MFC 再拖 20 年......

标签: c++ mfc hashmap unordered-map


【解决方案1】:

我做了非常简单的性能对比测试:

int nElements = 1000000;
CMap<int, int, CString, LPCTSTR> MfcHashTable;
MfcHashTable.InitHashTable(nElements);

// CMap insert
DWORD dwStart = ::GetTickCount();
for(int i=0; i<nElements; i++)
{
    CString sBase;
    sBase.AppendFormat(_T("Test String %d"), i);
    MfcHashTable[i] = sBase;
}

DWORD dwMfcMapInsert = ::GetTickCount() - dwStart;

// CMap lookup
CString sValue;

dwStart = ::GetTickCount();
for(int i=0; i<nElements; i++)
{
    MfcHashTable.Lookup(i, sValue);
}
DWORD dwMfcMapLookup = ::GetTickCount() - dwStart;

// std::map insert
std::map<int, CString> StdMap;
dwStart = ::GetTickCount();
for(int i=0; i<nElements; i++)
{
    CString sBase;
    sBase.AppendFormat(_T("Test String %d"), i);
    StdMap[i] = sBase;
}
DWORD dwStdMapInsert = ::GetTickCount() - dwStart;

//std::map lookup
dwStart = ::GetTickCount();
std::map<int, CString>::iterator it;
for(int i=0; i<nElements; i++)
{
    it = StdMap.find(i);
    CString sBase = it->second;
}
DWORD dwStdMapLookup = ::GetTickCount() - dwStart;

// std::unordered_map insert (hash table)
std::unordered_map<int, CString> StdUnordMap;
dwStart = ::GetTickCount();
for(int i=0; i<nElements; i++)
{
    CString sBase;
    sBase.AppendFormat(_T("Test String %d"), i);
    StdUnordMap[i] = sBase;
}
DWORD dwStdUnordMapInsert = ::GetTickCount() - dwStart;

//std::map lookup
dwStart = ::GetTickCount();
std::unordered_map<int, CString>::iterator it1;
for(int i=0; i<nElements; i++)
{
    it1 = StdUnordMap.find(i);
    CString sBase = it1->second;
}
DWORD dwStdUnordMapLookup = ::GetTickCount() - dwStart;

cout << dwMfcMapInsert << endl;
cout << dwMfcMapLookup << endl;

cout << dwStdMapInsert << endl;
cout << dwStdMapLookup << endl;

cout << dwStdUnordMapInsert << endl;
cout << dwStdUnordMapLookup << endl;

以下是 1000000 个元素Intel Core i5 2.5Ghz 8GB RAM (Lenovo ThinkPad X230) 上的结果:

MFC CMap insert: 1125
MFC CMap lookup: 125
std::map insert: 1406
std::map lookup: 172
std::unordered_map insert: 1578
std::unordered_map lookup: 140

令人惊讶的是,CMap 是这里的赢家。事实证明,丑陋的遗产CMap 毕竟还不错!

【讨论】:

  • 如果你包括破坏。 CMap 甚至更快,因为它使用与池分配器相当的内存块。如果您查看代码的构造,很明显 MFC Map 是“更好”的。 ;) 即使它已经过时了。
  • 很有趣,我也做过基准测试,我使用大 txt 字典文件中的单词和高性能 coutner 来测量时间,但我犯了一个错误,对于 std::unordered_map 我使用了 std: :string 类型的值或键,而对于 CMaps,我使用 CStrings,所以在这种情况下 unordered_map 击败 CMaps(数十毫秒),我将重写我的基准,我将为每个人使用 CString(因为我不能放一个std::string 作为 CMap 中的值,我不记得为什么它不起作用)
  • 我认为测试对CMap 有利,因为尺寸是已知的(InitHashTable),如果尺寸很大且未知,它会慢得多。同时unordered_map 没有利用reserve。只有CMap 的查找速度更快。
  • 你是对的。我没有使用它的原因是因为reserve() 没有在VS2010 中为unordered_map 实现。无论如何,我已经按如下方式实现了保留:StdUnordMap.rehash(std::ceil(nElements / StdUnordMap.max_load_factor())); 结果如下:插入为 1312,查找为 140。稍微好一点,但仍然不是最好的。
  • 只要你不使用池分配器,当你有很多条目时,MFC map 会特别击败 unordered_map。当哈希映射只是为临时操作创建时,删除所有项目的销毁阶段不是“短”操作。
【解决方案2】:

搜索“MFC CMap”需要 20 秒

Lookup 使用散列算法快速找到具有 与给定键完全匹配的键。

所以 big-O 效率将类似于 unordered_map

【讨论】:

  • 请否决投票者解释一下?该问题询问 CMap 是否具有与 mapunordered_map 相似的性能。我回答说它会类似于unordered_map。为什么这是一个糟糕的答案?
猜你喜欢
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多