cmapstringptr,hash_map,unordered_map的比较

downmooner 2011-04-11 05:26:12
大家好,我需要做一个遍历清理工作。
老项目是mfc的cmap,我修改成hash_map,发现速度很慢,遍历删除相差几百倍的时间,再后来试了下unordered_map,速度又比hash_map慢了一倍。

CMapStringToPtr:
CMapStringToPtr                      m_OnlineUserHash;
int nMaxOnlineUserCount = 120000;
m_OnlineUserHash.InitHashTable(nMaxOnlineUserCount*1.5);
for (int i = 0; i < 30000; ++i)
{
stringstream ss;
ss<<setw(20)<<setfill('0')<<i;

m_OnlineUserHash.SetAt(ss.str().c_str(),(void*)i);
}

void* pValue = NULL;
POSITION pos = NULL;
CString strKey;
DWORD dwtickbeg = GetTickCount();
for(pos = m_OnlineUserHash.GetStartPosition();pos != NULL;)
{
m_OnlineUserHash.GetNextAssoc(pos,strKey,pValue);
m_OnlineUserHash.RemoveKey(strKey);
}
DWORD dwEnd = GetTickCount() - dwtickbeg;


hash_map:
hash_map<string,int> hm(30000);
for (int i = 0; i < 30000; ++i)
{
stringstream ss;
ss<<setw(20)<<setfill('0')<<i;

//hm[ss.str()] = i;
hm.insert(make_pair(ss.str(),i));
}

DWORD dwtickbeg = GetTickCount();

hash_map<string,int>::iterator iter = hm.begin();
while (iter != hm.end())
{
const string &str = iter->first;
iter = hm.erase(iter);
}
DWORD dwEnd = GetTickCount() - dwtickbeg;


unordered_map:
unordered_map<string,int> hm(30000);
for (int i = 0; i < 30000; ++i)
{
stringstream ss;
ss<<setw(20)<<setfill('0')<<i;

//hm[ss.str()] = i;
hm.insert(make_pair(ss.str(),i));
}

DWORD dwtickbeg = GetTickCount();

unordered_map<string,int>::iterator iter = hm.begin();
while (iter != hm.end())
{
const string &str = iter->first;
iter = hm.erase(iter);
}
DWORD dwEnd = GetTickCount() - dwtickbeg;


但在都是release环境下,而且加上了#define _SECURE_SCL 0 开关

cmap 清理只要40ms
hash_map 1600ms
unordered_map 3000ms

这是为什么,我应该怎么改进?
...全文
280 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
帅得不敢出门 2011-04-12
  • 打赏
  • 举报
回复
这样遍历顺序删除追求速度似乎没有什么意义吧

查找后删除呢

效率的比较,感觉这个测试环境太单纯了。

downmooner 2011-04-12
  • 打赏
  • 举报
回复
我修改了下hash_map的清理方式,
hash_map<string,int> hm;
vector<string> vec(30000);
for (int i = 0; i < 30000; ++i)
{
stringstream ss;
ss<<setw(20)<<setfill('0')<<i;
vec[i] = ss.str();
//hm[ss.str()] = i;
hm.insert(make_pair(ss.str(),i));
}

DWORD dwtickbeg = GetTickCount();

for (int i = 0; i < 30000; ++i)
{
hm.erase(vec[i]);
}
DWORD dwEnd = GetTickCount() - dwtickbeg;


这样删除耗时30ms.比cmap快,单纯查询300W次也是hash_map快。

但unordered_map 说对复杂对象有支持比如string,但是我感觉测试比hash_map慢呀,比如上面的缓存unordered_map 耗时5秒多。
luciferisnotsatan 2011-04-12
  • 打赏
  • 举报
回复
CMapStringToPtr 应该也是hash的。可能有优化吧
冻结 2011-04-12
  • 打赏
  • 举报
回复
vc 的hash_map 是比较慢。
大意是vector<list>;
vs2010 的unordered_map和 hash_map 应该用的是一个结构实现的。

试试boost::unordered_map;
qq120848369 2011-04-11
  • 打赏
  • 举报
回复
按常理来说,这样已经很好了,再快点的话可以考虑自己实现hash_map,自定义内存池,无论多大的内存都从内存池里抠出来用,这样erase时内存的释放就快很多了。
downmooner 2011-04-11
  • 打赏
  • 举报
回复
downmooner 2011-04-11
  • 打赏
  • 举报
回复
hash_map 定义时没(30000);复制快了
 本次课程会带着大家学习Hash算法,从源码的角度去学习算法,更加容易理解的方式去学习,能够更高效的吸收学到的内容,也能培养出能够独自看源码,分析源码的能力。Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。  哈希表是根据设定的哈希函数H(key)和处理冲突方法将一组关键字映射到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。作为线性数据结构与表格和队列等相比,哈希表无疑是查找速度比较快的一种。  通过将单向数学函数(有时称为“哈希算法”)应用到任意数量的数据所得到的固定大小的结果。如果输入数据中有变化,则哈希也会发生变化。哈希可用于许多操作,包括身份验证和数字签名。也称为“消息摘要”。  简单解释:哈希(Hash)算法,即散列函数。它是一种单向密码体制,即它是一个从明文到密文的不可逆的映射,只有加密过程,没有解密过程。同时,哈希函数可以将任意长度的输入经过变化以后得到固定长度的输出。哈希函数的这种单向特征和输出数据长度固定的特征使得它可以生成消息或者数据。

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧