CMap InitHashTable大小

时间:2015-11-05 14:48:30

标签: visual-c++ mfc hashtable

在我的程序中,CMap的大小乘以1.2 IIRC 6230,这比我用InitHashTable(即6203)的大小要好。

我把另一个InitHashTable值作为素数:9973

这是正确的吗?或者我应该选择更接近素数到6203.或者我可以选择更大的素数?

2 个答案:

答案 0 :(得分:1)

这是使用VS2015的CMap的测试结果。它建议使用素数不会产生很大的差异,初始化是否比预期值多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

结果只是一个粗略的估计

答案 1 :(得分:0)

std::map使用红黑树CMap实现为哈希表。所以这是两个完全不同的容器。根据MSDN的最佳性能,哈希表大小应该是素数。为了最大限度地减少冲突,大小应该比最大的预期数据集大约20%。