map hash_map unordered_map 性能测试
来源:互联网 发布:aliyun阿里云邮箱登录 编辑:程序博客网 时间:2024/04/27 22:23
测试条件:
gcc version 4.2.1 20070719 [FreeBSD]
FreeBSD 7.2-RELEASE #0: Fri May 1 07:18:07 UTC 2009 root@driscoll.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 16核
Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 16核
测试程序说明:
先准备好n个字符串随机的MD5字符串做为key,然后分别对3个容器进行插入、遍历、查找、删除操作。
例如,n=100的时候,插入是指插入100个随机MD5 key;遍历是指对容器遍历一次;查找是指分别对这个100个随机的MD5 key做查找操作(即查找100次);删除是指挨个删除这个100个随机MD5 key。
测试数据如下表:
插入,单位us1001K10K100K1M10Mstd::map241283335888381214443908862233380std::ext/hash_map97166716466146025178844618512639std::tr1::unordered_map777728052530946583127429297
遍历,单位us1001K10K100K1M10Mstd::map1176842116031557001771906std::ext/hash_map474304218398804703444781575std::tr1::unordered_map112121
查找,单位us1001K10K100K1M10Mstd::map156211130456258709410026059064394std::ext/hash_map777748056569746602317705527std::tr1::unordered_map777728051544566595377600263
删除,单位us1001K10K100K1M10Mstd::map291364149584472414667589792491113std::ext/hash_map8986990688652496476710372650std::tr1::unordered_map494804879330873950984369617
结论:
1. std::tr1::unordered_map 与 std::ext/hash_map
任何情况下,如果要在这两个容器之间选择的话,我们毫不犹豫应该选择 unordered_map。因为他的性能在上述4中操作中均优于 hash_map,甚至可以说远远优于 hash_map。
2. std::tr1::unordered_map 与 std::map
map的性能总体来说是最差的。但是,当我们需要一个有序的关联容器的时候,我们必须选择std::map,因为 unordered_map 内部元素不是有序的,这一点从名字都可以看出来。除此之外都应该选择 unordered_map 。
3. 上述测试中,unordered_map 的遍历性能几乎是常数级别的,与常识不太相符,需要再研究研究。
附录:贴上源代码
说明:与测试程序稍有区别,这里的源码里没有MD5相关的代码以确保其他人能比较方便的直接拿去编译运行。
如有错误还请跟帖指出,非常感谢。
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <list>
- #include <map>
- #include <sys/time.h>
- #include <ext/hash_map>
- #include <tr1/unordered_map>
- namespace zl
- { //{{{
- struct equal_to
- {
- bool operator()(const char* s1, const char* s2) const
- {
- return strcmp(s1, s2) == 0;
- }
- };
-
- struct hash_string
- : public std::unary_function<std::string, std::size_t>
- {
- std::size_t
- operator()(const std::string& __s) const
- #ifdef __linux__
- { return std::tr1::Fnv_hash<>::hash(__s.data(), __s.length()); }
- #else
- { return std::tr1::_Fnv_hash<>::hash(__s.data(), __s.length()); }
- #endif
- };
-
- struct hash_charptr
- : public std::unary_function<const char*, std::size_t>
- {
- std::size_t
- operator()(const char* __s) const
- #ifdef __linux__
- { return std::tr1::Fnv_hash<>::hash(__s, strlen(__s)); }
- #else
- { return std::tr1::_Fnv_hash<>::hash(__s, strlen(__s)); }
- #endif
- };
- }//}}}
- typedef std::list<std::string> string_list;
- typedef std::map<std::string, int> string_map;
- typedef __gnu_cxx::hash_map<std::string, int, zl::hash_string> string_hash_map;
- typedef std::tr1::unordered_map<std::string, int> string_unordered_map;
- void fill_list(string_list& slist, size_t count);
- uint64_t current_usec();
- int main( int argc, char* argv[] )
- {
- if (argc != 2 && argc != 3)
- {
- fprintf(stderr, "Usage:%s test_count rehash\n", argv[0]);
- fprintf(stderr, "For example:%s 10000 rehash\n", argv[0]);
- return -1;
- }
- size_t count = atoi(argv[1]);
- bool rehash = false;
- if (argc == 3)
- {
- rehash = true;
- }
- string_map smap;
- string_hash_map shash_map;
- string_unordered_map sunordered_map;
- if (rehash)
- {
- sunordered_map.rehash(count);
- }
- string_list slist;
- fill_list(slist, count);
- uint64_t start = 0;
- uint64_t end = 0;
- uint64_t map_insert_us = 0;
- uint64_t hash_map_insert_us = 0;
- uint64_t unordered_map_insert_us = 0;
- uint64_t map_traverse_us = 0;
- uint64_t hash_map_traverse_us = 0;
- uint64_t unordered_map_traverse_us = 0;
- uint64_t map_find_us = 0;
- uint64_t hash_map_find_us = 0;
- uint64_t unordered_map_find_us = 0;
- uint64_t map_delete_us = 0;
- uint64_t hash_map_delete_us = 0;
- uint64_t unordered_map_delete_us = 0;
- // Insert test
- {//{{{
- string_list::iterator it(slist.begin());
- string_list::iterator ite(slist.end());
- //map insert
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- smap[*it] = i;
- }
- end = current_usec();
- map_insert_us = end - start;
- //hash_map insert
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map[*it] = i;
- }
- end = current_usec();
- hash_map_insert_us = end - start;
- //unordered_map insert
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map[*it] = i;
- }
- end = current_usec();
- unordered_map_insert_us = end - start;
- }//}}}
- // Traverse test
- {//{{{
- //map traverse
- {
- string_map::iterator it(smap.begin());
- string_map::iterator ite(smap.end());
- start = current_usec();
- for (int i = 0; it != ite; ++it)
- {
- i++;
- }
- end = current_usec();
- map_traverse_us = end - start;
- }
- //hash_map traverse
- {
- string_hash_map::iterator it(shash_map.begin());
- string_hash_map::iterator ite(shash_map.end());
- start = current_usec();
- for (int i = 0; it != ite; ++it)
- {
- i++;
- }
- end = current_usec();
- hash_map_traverse_us = end - start;
- }
- //unordered_map traverse
- {
- string_unordered_map::iterator it(sunordered_map.begin());
- string_unordered_map::iterator ite(sunordered_map.end());
- start = current_usec();
- for (int i = 0; it != ite; ++it)
- {
- i++;
- }
- end = current_usec();
- unordered_map_traverse_us = end - start;
- }
- }//}}}
- // Find test
- {//{{{
- string_list::iterator it(slist.begin());
- string_list::iterator ite(slist.end());
- //map find
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- smap[*it] = i;
- }
- end = current_usec();
- map_find_us = end - start;
- //hash_map find
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map[*it] = i;
- }
- end = current_usec();
- hash_map_find_us = end - start;
- //unordered_map find
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map[*it] = i;
- }
- end = current_usec();
- unordered_map_find_us = end - start;
- }//}}}
- // Delete test
- {//{{{
- string_list::iterator it(slist.begin());
- string_list::iterator ite(slist.end());
- //map delete
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- smap.erase(*it);
- }
- end = current_usec();
- map_delete_us = end - start;
- //hash_map delete
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map.erase(*it);
- }
- end = current_usec();
- hash_map_delete_us = end - start;
- //unordered_map delete
- it = slist.begin();
- start = current_usec();
- for (int i = 0; it != ite; ++it, ++i)
- {
- shash_map.erase(*it);
- }
- end = current_usec();
- unordered_map_delete_us = end - start;
- }//}}}
- //stat output
- std::cout << " insert, count " << count << std::endl;
- std::cout << " std::map " << map_insert_us << " us\n";
- std::cout << " std::ext/hash_map " << hash_map_insert_us << " us\n";
- std::cout << "std::tr1::unordered_map " << unordered_map_insert_us << " us\n";
- std::cout << "\n";
- std::cout << " traverse, count " << count << std::endl;
- std::cout << " std::map " << map_traverse_us << " us\n";
- std::cout << " std::ext/hash_map " << hash_map_traverse_us << " us\n";
- std::cout << "std::tr1::unordered_map " << unordered_map_traverse_us << " us\n";
- std::cout << "\n";
- std::cout << " find, count " << count << std::endl;
- std::cout << " std::map " << map_find_us << " us\n";
- std::cout << " std::ext/hash_map " << hash_map_find_us << " us\n";
- std::cout << "std::tr1::unordered_map " << unordered_map_find_us << " us\n";
- std::cout << "\n";
- std::cout << " delete, count " << count << std::endl;
- std::cout << " std::map " << map_delete_us << " us\n";
- std::cout << " std::ext/hash_map " << hash_map_delete_us << " us\n";
- std::cout << "std::tr1::unordered_map " << unordered_map_delete_us << " us\n";
-
- return 0;
- }
- void fill_list(string_list& slist, size_t count)
- {
- for (size_t i = 0; i < count; ++i)
- {
- std::ostringstream oss;
- oss << i;
- //slist.push_back(MD5::getHexMD5(oss.str().c_str(), oss.str().length()));
- slist.push_back(oss.str());
- }
- }
- uint64_t current_usec()
- {
- struct timeval tv;
- gettimeofday( &tv, NULL );
- return tv.tv_sec * 1000 * 1000 + tv.tv_usec;
- }
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试
- map hash_map unordered_map 性能测试 统计
- map, hash_map,unordered_map与性能测试
- map hash_map unordered_map 性能比较
- 关于map、hash_map 和 unordered_map 的简单性能测试
- map, hash_map,unordered_map介绍
- map, hash_map,unordered_map
- unordered_map map hash_map
- map, hash_map,unordered_map
- hash_map,map,unordered_map效率
- map, hash_map,unordered_map
- hdu 2532 Engine 模拟好题 字符串的处理
- js中showModalDialog和showModelessDialog的使用
- JS的ShowModalDialog模式窗体传值
- ShowModalDialog数据缓存的清除方法
- 黑马程序员_IO流(三)
- map hash_map unordered_map 性能测试
- window.showModalDialog以及window.open用法简介
- H264编码
- 滚动排序效果
- iframe的高度随内容的多而自动增长
- JavaScript创建弹出窗口
- <base target="_self">
- 最基本的弹出窗口代码
- cocos2d-x 实战 Dots - 序