1. 程式人生 > >vector和map的效率簡要比較

vector和map的效率簡要比較

專案中要對一些資料結構進行存取,而專案本身對時間延時比較敏感,在使用vector還是map上著實糾結了一番,主要某些資料量比較小,才有此糾結。

而且想搞明白,到底大到什麼資料量該用map?做了一些簡單的測試,見下。

首先,不管是vector還是map,請儘量存取指標,否則在存取時會有資料拷貝帶來不必要的時間損失。通常用int和string做key的場景比較普遍(我的專案即如此),能用int作key就用int作key,效率比string高。

測試方法:

給vector和map容器中分別塞入1,000,000個數據(順序插入,有序的),然後設定一個查詢目標,vector順序遍歷查詢,map用key查詢,對比查詢時間。使用高精度定時器計時。

基本結論:

1、unordered_map比map快

2、vector查詢14次,基本和unordered_map查詢一次耗時相當(int和string做key差別不大)

3、string作key,vector查詢100次,基本和map查詢一次耗時相當;int作key,vector查詢28次,基本和map查詢一次耗時相當

4、boost的unordered_map和map與STL的效率基本相同

因此:拋棄map,用unordered_map吧。如果明確資料量小,比如小於14個,就用vector或陣列,效率更高。

unordered_map<string,...>


unordered_map<int,...>


map<string, ...>


map<int,...>


測試程式碼:

#include <windows.h>
#include <string>
#include <iostream>
#include <iomanip>

#include <map>
#include <unordered_map>
#include <boost/unordered_map.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <algorithm>

using namespace std;

struct MyStruct
{
	MyStruct() {}
	MyStruct(int x, string s) : i(x), str(s) {}

	int i;
	string str;
};

#define VECTOR_TEST_DEF std::vector<MyStruct*>

//#define STRING_KEY

#define MAP_TYPE std::map
//#define MAP_TYPE std::unordered_map
//#define MAP_TYPE boost::unordered_map
//#define MAP_TYPE boost::interprocess::map

#define MAP_TYPE_STR "std::map"
//#define MAP_TYPE_STR "std::unordered_map"
//#define MAP_TYPE_STR "boost::unordered_map"
//#define MAP_TYPE_STR "boost::interprocess::map"

#ifdef STRING_KEY
#define MAP_TEST_DEF MAP_TYPE<string, MyStruct*>
#define TARGET_VAL "100"
#else
#define MAP_TEST_DEF MAP_TYPE<int, MyStruct*>
#define TARGET_VAL 28
#endif

#define DATA_COUNT 1000000
#define LOOP_COUNT 10000

LARGE_INTEGER m_counterFreq;
MyStruct* vectorRet;
MyStruct* mapRet;

string ToString(int d)
{
	char szBuf[8];
	sprintf_s(szBuf, "%d", d);
	return string(szBuf);
}

LONGLONG GetMicroSecCounter()
{
	LARGE_INTEGER counter = { 0 };
	QueryPerformanceCounter(&counter);
	return counter.QuadPart * 1000000 / m_counterFreq.QuadPart;
}

string GetTimeDiffMillSecStr(LONGLONG microCounterBegin, LONGLONG micoCounterEnd)
{
	double dblDiff = (micoCounterEnd - microCounterBegin) / (double)1000;

	char szBuf[32];
	sprintf_s(szBuf, "%.3fms", dblDiff);
	return szBuf;
}

void TestVectorMap()
{
	VECTOR_TEST_DEF vecTest;
	MAP_TEST_DEF mapTest;

	QueryPerformanceFrequency(&m_counterFreq);

	vecTest.resize(DATA_COUNT);
	for (int i = 0; i < DATA_COUNT; i++)
	{
		string str = ToString(i);
		MyStruct* t = new MyStruct(i, str);
		vecTest[i] = t;
#ifdef STRING_KEY
		mapTest[str] = t;
#else
		mapTest[i] = t;
#endif // STRING_KEY

	}

	LONGLONG t1 = HighPreciseTickCounter::GetMicroSecCounter();
	VECTOR_TEST_DEF::iterator iterVec;
	for (int i = 0; i < LOOP_COUNT; i++)
	{
		iterVec = vecTest.begin();
		for (; iterVec != vecTest.end(); iterVec++)
		{
#ifdef STRING_KEY
			if (!strcmp((*iterVec)->str.c_str(), TARGET_VAL))
#else
			if ((*iterVec)->i == TARGET_VAL)
#endif // STRING_KEY
			{
				vectorRet = *iterVec;
				break;
			}
		}
	}

	LONGLONG t2 = HighPreciseTickCounter::GetMicroSecCounter();

	MAP_TEST_DEF::iterator iterMap;
	for (int i = 0; i < LOOP_COUNT; i++)
	{
#ifdef STRING_KEY
		iterMap = mapTest.find(TARGET_VAL);
#else
		iterMap = mapTest.find(TARGET_VAL);
#endif // STRING_KEY

		if (iterMap != mapTest.end())
			mapRet = iterMap->second;
	}

	LONGLONG t3 = HighPreciseTickCounter::GetMicroSecCounter();

#ifdef STRING_KEY
	string keyType = "<string, MyStruct*>";
#else
	string keyType = "<int, MyStruct*>";
#endif // STRING_KEY

	std::cout << setiosflags(ios::left);
	std::cout << setw(20) << "Find Target Val: " << TARGET_VAL << std::endl;
	std::cout << setw(20) << "Find Loop Count: " << LOOP_COUNT << std::endl;
	std::cout << setw(20) << "Find Cost Vector: " << GetTimeDiffMillSecStr(t1, t2) << std::endl;
	std::cout << setw(20) << "Find Cost Map: " << GetTimeDiffMillSecStr(t2, t3) << "   " << MAP_TYPE_STR << keyType << std::endl;

	cout << setw(20) << "Vector Find: " << vectorRet->str << endl;
	cout << setw(20) << "Map Find: " << mapRet->str << endl;

	for (int i = 0; i < DATA_COUNT; i++)
	{
		MyStruct* t = vecTest[i];
		delete t;
	}
}