2015-12-13 123 views
1

相比有很好的性能MFC CMapstd::unordered_mapstd::map相比有很好的性能,我问这个问题是因为我要在我的公司启动一个项目,并加速开发我要开始一个现有的“类似”项目,但在这最后,有MFC CMap(哈希表地图)我认为使用std::unordered_map可能会提高性能。我在互联网上没有找到任何与CMap相关的基准或好文章。 否则,使用std::unordered_map我是否还必须修复散列表的大小,如CMap以避免冲突和性能问题?MFC CMap与std :: unordered_map或std :: map

+2

***我没有在interne上找到与CMap相关的任何基准测试或好文章***为什么不用自己的数据集进行基准测试?您将在硬件上使用哪种数据集?在生产中使用? – drescherjm

+3

CMap没有移动支持(如果您想从函数返回一个参数,您必须始终将其作为输出参数传递),并且不会在调试器中的监视窗口中显示任何有用内容。你还必须编写像'CMap map;'而不是'std :: unordered_map map;'的代码。如果我是你,我甚至不会考虑使用它 - 但这取决于你。 –

+0

drescgerjm,我在过去做过(std :: map vs CMap),但我不相信......但如果我在这里没有得到答案,我会做另一个基准测试(CMaps vs unordered_map)。 – Aminos

回答

6

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

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; 

下面是结果百万元Intel酷睿i5 2.5Ghz的8GB内存(联想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毕竟不是那么糟糕!

+2

如果你包含破坏。 CMap甚至更快,因为它使用与池分配器相当的内存块。如果你仔细研究代码的构造,它会清楚地知道MFC Map是“更好的”。 ;)即使它过时了。 – xMRi

+0

有趣的是,我也做了一个基准测试,我用一个大的txt字典文件和高性能的coutner来测量时间,但我做了一个错误,对于std :: unordered_map我使用了std :: string类型的值或键,而对于CMaps,我使用了CStrings,所以在这种情况下,unordered_map击败CMaps(几十毫秒),我将重写我的基准测试并为每个人提供CString(因为我无法将std :: string作为值在CMap中,我不记得它为什么不起作用) – Aminos

+1

我认为测试是在'CMap'的青睐,因为大小是已知的('InitHashTable'),它会慢得多,如果规模很大,并且未知。同时'unordered_map'没有利用'reserve'。 'CMap'只查找速度更快。 –

-3

好20秒搜索“MFC的CMap”发现

查找使用哈希算法来与 关键一个与给定键匹配快速查找地图元素。

因此,大O效率将会像unordered_map

+0

可否请投票者解释?这个问题问CMap是否具有与'map'或'unordered_map'类似的性能。我回答说它会和'unordered_map'类似。为什么这是一个不好的答案? –