STL의 map,array의 성능에 차이는 없을까?
key값이 string인 경우와 int인 경우의 차이는 얼마나 될까?
이것을 확인하기 위해서 아래와 같이 간단한 성능 테스트 프로그램을 작성해봤습니다.
stringMapTC()는 strStr 에 들어있는 string들을 key로 하여 map의 요소에 접근하는 테스트
stringUnorderedMapTC()는 strStr 에 들어있는 string들을 key로 하여 unordered_map의 요소에 접근하는 테스트
intMapTC()는 int 값을 key로 하여 map의 요소에 접근하는 테스트
intArrayTC()는 stl::array로 요소에 접근하는 테스트
cArrayTC()는 stl container가 아닌 srcStr[] 에서 직접 35번 요소에 접근하는 테스트
테스트 결과 - 10000회 수행 시간 (초)
함수 | 데이터 형식 | 1 | 2 | 3 | 4 |
stringMapTC() |
std::map <const std::string, int> |
0.0049 | 0.0052 | 0.0054 | 0.0053 |
stringUnorderedMapTC() | std::unordered_map <const std::string, int> |
0.0018 | 0.0019 | 0.0019 | 0.0019 |
intMapTC() |
std::map <int, const std::string> |
0.0006 | 0.0008 | 0.0008 | 0.0008 |
intArrayTC() |
std::array <std::string, 100> |
0.0001 | 0.0001 | 0.0001 | 0.0001 |
cArrayTC() |
char* srcStr[] | 0.0001 | 0.0001 | 0.0001 | 0.0001 |
stringMapTC의 경우는 key compare를 위해 string 을 비교해야 하기에 가장 오래걸립니다.
stringUnorderedMapTC는 map에 비해 약 2.7배 정도 빠른 성능을 보입니다.
code가 길어서 그렇지 성능을 높이려면 map 쓰는 곳을 모두 unordered_map으로 변경하면 비약적인(?) 성능 향상이 이뤄지겠네요 ^^.
intMapTC의 경우는 key값이 int라서 string 을 key로 사용하는 것에 비해 많이 빠릅니다. 그러나 stl::array에 비해서는 느리게 결과가 나왔습니다.
당연히 intArrayTC의 경우는 당연히 map보다는 빠를 수 밖에 없습니다. 전체 서치가 아니라 array의 index (= array[index]) 를 key처럼 사용하기 때문에 key값이 당연히 정렬이 되어있어서 빠를 수 밖에 없습니다.
cArrayTC() 와 비슷한 결과가 나올 수 밖에 없습니다.
[source code]
#include <time.h>
#include <map>
#include <unordered_map>
#include <array>
#include <string>
using namespace std;
const char *srcStr[] =
{
"hello"
"bounds",
"contentBounds",
"contentOpacity",
"renderOperation",
"opacity",
"showState",
"anchor",
"anchorZ",
"transform",
"childrenTransform",
"zPosition",
"zOrderGroup",
"clipToParent",
"clipChildren",
"projection",
"surfaceOpaque",
"name",
"propertyPropagation",
"implicitAnimation",
"detach",
"attach",
"bounds.",
"bounds.position",
"bounds.size",
"transform.",
"transform.rotation.x",
"transform.rotation.y",
"transform.rotation.z",
"transform.scale.x",
"transform.scale.y",
"transform.scale.z",
"transform.translation.x",
"transform.translation.y",
"transform.translation.z",
"transform.rotation.anchor.x",
"transform.rotation.anchor.y",
"transform.rotation.anchor.z",
"transform.scale.anchor.x",
"transform.scale.anchor.y",
"transform.scale.anchor.z",
"transform.rotation.xy",
"transform.scale.xy",
"transform.translation.xy",
"transform.rotation.anchor.xy",
"transform.scale.anchor.xy",
"childrenTransform.",
"childrenTransform.rotation.x",
"childrenTransform.rotation.y",
"childrenTransform.rotation.z",
"childrenTransform.scale.x",
"childrenTransform.scale.y",
"childrenTransform.scale.z",
"childrenTransform.translation.x",
"childrenTransform.translation.y",
"childrenTransform.translation.z",
"childrenTransform.rotation.anchor.x",
"childrenTransform.rotation.anchor.y",
"childrenTransform.rotation.anchor.z",
"childrenTransform.scale.anchor.x",
"childrenTransform.scale.anchor.y",
"childrenTransform.scale.anchor.z",
"childrenTransform.rotation.xy",
"childrenTransform.scale.xy",
"childrenTransform.translation.xy",
"childrenTransform.rotation.anchor.xy",
"childrenTransform.scale.anchor.xy",
"__showOpacity",
};
double stringMapTC()
{
std::map<const std::string, int> strMap;
int i = 0;
for (auto str : srcStr)
{
strMap.insert({str, i++});
}
int v = 0;
clock_t start = clock();
for (int j = 0; j < 10000; j++)
{
v = strMap["childrenTransform.rotation.anchor.x"];
}
clock_t end = clock();
return (double)(end - start) / CLOCKS_PER_SEC;
}
double stringUnorderedMapTC()
{
std::unordered_map<std::string, int> strMap;
int i = 0;
for (auto str : srcStr)
{
strMap.insert({str, i++});
}
int v=0;
clock_t start = clock();
for (int j = 0; j < 10000; j++)
{
v= strMap["childrenTransform.rotation.anchor.x"];
}
clock_t end = clock();
return (double)(end - start) / CLOCKS_PER_SEC;
}
double intMapTC()
{
std::map<int, const std::string> strMap;
int i = 0;
for (auto str : srcStr)
{
strMap.insert({i++, str});
}
clock_t start = clock();
std::string v;
for (int j = 0; j < 10000; j++)
{
v= strMap[35];
}
clock_t end = clock();
return (double)(end - start) / CLOCKS_PER_SEC;
}
double intArrayTC()
{
std::array<std::string, 100> strMap;
int i = 0;
for (auto str : srcStr)
{
strMap[i++] = str;
}
clock_t start = clock();
std::string v;
for (int j = 0; j < 10000; j++)
{
v = strMap[35];
}
clock_t end = clock();
return (double)(end - start) / CLOCKS_PER_SEC;
}
double cArrayTC()
{
clock_t start = clock();
std::string v;
for (int j = 0; j < 10000; j++)
{
v = srcStr[35];
}
clock_t end = clock();
return (double)(end - start) / CLOCKS_PER_SEC;
}
#define PRINT_TC(_FUNC) \
{ \
double res = _FUNC(); \
printf("%.4f %s()\n", res, #_FUNC); \
}
int main(void)
{
PRINT_TC(stringMapTC);
PRINT_TC(stringUnorderedMapTC);
PRINT_TC(intMapTC);
PRINT_TC(intArrayTC);
PRINT_TC(cArrayTC);
}
테스트 결과
$ ./main
0.0054 stringMapTC()
0.0021 stringUnorderedMapTC()
0.0009 intMapTC()
0.0001 intArrayTC()
0.0001 cArrayTC()
'C++11,14 (modern C++)' 카테고리의 다른 글
C++ 11과 C++ 99 를 동시에 지원하기 위해서 feature를 구분할 때 유용한 팁 (0) | 2016.09.07 |
---|---|
gcc와 c++ feature (0) | 2016.07.18 |
effective modern c++: 멤버 함수 사용 제한을 delete 키워드로 하는 것이 낫다. (2) | 2016.02.11 |
effective modern c++: typedef 보다는 using (0) | 2016.02.11 |
effective modern c++: noexcept 선언 (0) | 2016.02.05 |