在我的程序,的CMap
倍1.2 IIRC 6230這是優於我以前InitHashTable
的尺寸(其是6203)的大小。CMap的InitHashTable大小
我把另一InitHashTable
值是質數:9973
因此,這是正確的嗎?或者我應該選擇一個更接近6203的質數。或者,我可以選擇一個更大的質數?
在我的程序,的CMap
倍1.2 IIRC 6230這是優於我以前InitHashTable
的尺寸(其是6203)的大小。CMap的InitHashTable大小
我把另一InitHashTable
值是質數:9973
因此,這是正確的嗎?或者我應該選擇一個更接近6203的質數。或者,我可以選擇一個更大的質數?
這是CMap
與VS2015的測試結果。它表明使用素數並沒有太大的區別,如果初始化比預期值高20%或更少,這並不重要。
有有或無質數或初始化沒有錯誤。我會假設在CMap
的文檔中提到的「碰撞」與性能有關。
對於更大的數據集,你可以使用預期的數據大小。例如,如果預期的大小是6,000,那麼只需使用map.InitHashTable(6000)
。默認值爲17,較低的值會降低性能。
還爲std::map
測試結果,並不需要初始化和速度非常快。
void test()
{
CString msg;
//build test vector
int size = 100000;
std::vector<CString> vs;
for (int i = 0; i < size; i++)
{
CString s;
s.Format(L"str%d", i);
vs.push_back(s);
}
{//using prime number, 20% larger than expected size
int t = GetTickCount();
int init_size = 120011;
CMap<LPCTSTR, LPCTSTR, int, int> map;
map.InitHashTable(init_size);
for (int i = 0; i < size; i++)
map[vs[i]] = i;
msg.AppendFormat(L"CMap Initialized: %d, time:%d\n", init_size, GetTickCount() - t);
}
{//using non-prime number and 20% less than expected size
int t = GetTickCount();
int init_size = 80000;
CMap<LPCTSTR, LPCTSTR, int, int> map;
map.InitHashTable(init_size);
for (int i = 0; i < size; i++)
map[vs[i]] = i;
msg.AppendFormat(L"CMap Initialized: %d, time:%d\n", init_size, GetTickCount() - t);
}
{//using non-prime number and default initialization (m_nHashTableSize=17)
int t = GetTickCount();
CMap<LPCTSTR, LPCTSTR, int, int> map;
for (int i = 0; i < size; i++)
map[vs[i]] = i;
msg.AppendFormat(L"CMap Initialized: %d, time:%d\n", 17, GetTickCount() - t);
}
{//std::map test
int t = GetTickCount();
std::map<CString, int> mp;
for (int i = 0; i < size; i++)
mp[vs[i]] = i;
msg.AppendFormat(L"std::map time:%d\n", GetTickCount() - t);
}
//error test:
int init_size = 1000; //only a fraction of expected size!
CMap<LPCTSTR, LPCTSTR, int, int> map;
map.InitHashTable(init_size);
for (int i = 0; i < size; i++)
map[vs[i]] = i;
for (int i = 0; i < size; i++)
{
if (map[vs[i]] != i)
{
AfxMessageBox(L"errorTest - fail");
return;
}
}
msg.AppendFormat(L"no error");
AfxMessageBox(msg);
}
測試結果:(上優化釋放模式)
CMap Initialized: 120011, time:31
CMap Initialized: 80000, time:47
CMap Initialized: 17, time:5110
std::map time:78
no error
結果僅僅是一個粗略的估計
我也做了一個基準測試,哈希映射的大小即使比預期的大小太小,也沒有數據丟失。然而,性能顯着下降(例如,std :: map爲0.5s,而在訪問數據時具有非常小散列大小的CMap
std::map
使用紅黑樹和CMap
爲哈希表實現。所以這些是兩個完全不同的容器。根據MSDN的最佳性能,哈希表大小應該是一個素數。爲了儘量減少衝突,規模應該比最大的預期數據集大約大20%。
關於第二個想法,'CMap'似乎有一定的優勢,如果你知道的初始大小。 'std :: map'不能設置初始大小,所以它比較慢。我運行了一些測試,它顯示了是否存在質數並不重要,如果初始大小增大20%,則無關緊要。只要初始大小大致在應該的位置,它就會很快。 –
Barmak,如果我使用一個大的散列表(比假定的大小大100%),我會碰到像碰撞一樣的問題嗎? (請原諒我的愚蠢問題) – Aminos
Aminos,文檔含糊不清。 「碰撞」可能是指性能問題。如果這是一個錯誤,那麼你想消除衝突,而不是最小化。我認爲'CMap'試圖分配一個新項目,它可能會看到與現有項目的衝突,所以它必須分配一個新項目,這浪費了幾個納秒。也許這就是文檔所警告的。我在另一個答案中添加了一些測試。 –
使用'的std :: map'如果可能的話。 'CMap'對它的質數指令很奇怪。 –
我真的想跟着你的意見,但我與舊代碼工作,這不是我的業務進行修改:\ – Aminos