寫了一個模組用戶端和伺服器共用,為了加快查詢速度,用了hash_map,今天一個兄弟老盧測試說將其中的hash_map替換成map後速度更快,有點暈。自己寫了一段代碼在Windows下用Visual Studio C++測試hashmap。
首先說明,hashmap目前還沒有進入C++的規範,但是大部分廠商都實現了這個容器,測試的hashmap有兩種:
l Visual Studio 2003自己預設帶的hash_map,
l STLport的hash_map
當然用過Visual Studio預設內建的hashmap的兄弟會知道,其和SGI的一脈的STL實現不太一樣,包括模板聲明方式等都自成一套。所以其實使用的時候還要注意。這兒就不囉嗦這個問題了。同時麻煩大家注意我測試的版本是2003,使用的是DEBUG版本。
測試代碼如下,如果你覺得枯燥,可以跳過這段看代碼直接看結果,代碼其中用了ACE的一些代碼測試時間差:
#include <stdio.h>
#include <iostream>
#include <map>
#include <hash_map>
#include <ace/OS.h>
#include <ace/Time_Value.h>
void test_hash_map()
{
ACE_Time_Value tvStart(0);
ACE_Time_Value tvEnd(0);
ACE_Time_Value tvPassTime(0);
tvStart = ACE_OS::gettimeofday();
hash_map<size_t,int> int_hash_map;
//測試10萬次
const size_t TEST_NUMBER = 10*10000;
//注意這行代碼,VS.NET預設的STL沒有這個函數的,而STLPort的實現有這個函數
int_hash_map.resize(TEST_NUMBER);
//順序插入一組資料
for (size_t i= 0;i<TEST_NUMBER;++i)
{
int_hash_map[i]=0;
}
//查詢20萬次,一般能查詢到,一半不能查詢到
for (size_t i= 0;i<2*TEST_NUMBER;++i)
{
int_hash_map.find(i);
}
//得到毫秒的時間差
tvEnd = ACE_OS::gettimeofday();
tvPassTime = tvEnd - tvStart;
cout<<"test_hash_map gettimeofday :"<<tvPassTime.msec()<<" "<<endl;
};
void test_map()
{
ACE_Time_Value tvStart(0);
ACE_Time_Value tvEnd(0);
ACE_Time_Value tvPassTime(0);
tvStart = ACE_OS::gettimeofday();
map<size_t,int> int_map;
//測試10萬個資料
const size_t TEST_NUMBER = 10*10000;
for (size_t i= 0;i<TEST_NUMBER;++i)
{
int_map[i]=0;
}
for (size_t i= 0;i<2*TEST_NUMBER;++i)
{
int_map.find(i);
}
//得到毫秒的時間差
tvEnd = ACE_OS::gettimeofday();
tvPassTime = tvEnd - tvStart;
cout<<"test_map gettimeofday :"<<tvPassTime.msec()<<" "<<endl;
};
int main(int argc, char* argv[])
{
for (int j=0;j<10;++j)
{
test_hash_map();
test_map();
}
return 0;
}
使用Visual Studio 預設的STL的測試結果是,比較讓人驚訝的是hash_map的速度不比map快多少,(在我一個同事的VS2005的機器上測試,map居然比hash_map快),節約篇幅,唯寫了2組測試結果。其他測試結果偏差不大。
test_hash_map gettimeofday :3093
test_map gettimeofday :3484
test_hash_map gettimeofday :3250
test_map gettimeofday :3531
而使用STLPort的測試結果如下:hash_map速度比MS的實現快了一倍多,map也比MS的實現快。
test_hash_map gettimeofday :1312
test_map gettimeofday :2359
test_hash_map gettimeofday :1312
test_map gettimeofday :2375
而由於MS的hash_map實現沒有resize函數,我單獨對STLport的實現測試了先使用resize函數的結果如下,大家可以發現如果先使用resize函數,速度可以得到更大的提高。
test_hash_map gettimeofday :1015
test_map gettimeofday :2343
test_hash_map gettimeofday :1031
test_map gettimeofday :2375
我對STLport的hash_map的實現比較熟悉,應該就是hash因子的數組加List存放資料。而MS Visual Studio的實現我初步瀏覽了一下,應該也類似,具體原因就說不清了,我也不太想耗費體能找出問題的癥結所在,就只看錶面現象吧。
所以大家在使用Visual Studio 的hash_map的時候要當心了,
l 第一,這個hash_map實現不怎麼快,
l 第二,微軟的實現不地道,,基本可以肯定SGI的實現會是預設的標準,有興趣可以看看BOOST的unordered_map,未來的hash_map應該就是這個樣子。
l 第三,沒有resize函數,這樣幾乎可以肯定,這個實現的大容量時的表現應該很爛。我的同事測試在2005下測試上面的程式,測試數量改為了100萬後,他的說法是他最後沒有耐心等待結果了。而我用2003的STLport測試結果是10s多完成測試。為什麼我敢肯定,建議大家去看看hash_map的實現。
另外inmore看了我的測試結果說好像MS實現的迭代器遍曆要快,我測試了一下,發現果真如此,難道微軟的工程師昏了頭,最佳化hash_map的迭代器遍曆去了,但多少懷疑這和MS實現還是有一定得關係。
Microsoft的自己的編譯器,實現的東西居然比別人慢一個數量級,MS的工程師應該羞愧一個。測試限於2003和2005,沒有涉及2008,但我基本也不抱太大希望。當然,我在這兒也不勸你把所有的東西替換為STLport的實現,為啥呢?如果你用的第三方庫很多,這個成本過高了。除非你和我一樣,是一個在Windows下調試伺服器代碼的異類。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/fullsail/archive/2009/06/01/4230312.aspx