본문 바로가기

개발 Note/C++11,14 (modern C++)

stl : map 과 array 성능비교.

반응형

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()