CMapは万能か?他、CStringArray

  • デル株式会社
  • 仕事でCMapとCStringArrayどっちが早いのかという状況になって、シーケンシャルアクセスする状況では
    CMapよりもCStringArrayのほうが速いのでは?ということになり、検証してみた。

    各処理を100万回実行。

    
    class Test
    {
    public:
        char aaa[256];
        Test(){}
    };
    class Test2
    {
    public:
        CString aaa;
        Test2(){}
    };
    
    typedef struct _STRACT
    {
        char str[256];
    }STRACT;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int ii = 0;
        CString str;
        long t = 0;
        CMap<UINT,UINT,CString,CString> map;
        CStringArray Freearr;
        char ch[256] = {NULL};
    
        //---------------------------------------------------
        // CMap
        //---------------------------------------------------
        //set CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            map[ii] = "str";
        }
        t = GetTickCount() -t;
        sprintf(ch,"CMap set 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = map[ii];
        }
        t = GetTickCount() -t;
        sprintf(ch,"CMap get 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //---------------------------------------------------
        // CStringArray サイズ未設定
        //---------------------------------------------------
        //set CStringArray
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            Freearr.Add("str");
        }
        t = GetTickCount() -t;
        sprintf(ch,"CStringArray::Add 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = Freearr.GetAt(ii);
        }
        t = GetTickCount() -t;
        sprintf(ch,"CStringArray::GetAt 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //---------------------------------------------------
        // CStringArray サイズ設定
        //---------------------------------------------------
        CStringArray FixedArr;
    
        //set CStringArray
        t = GetTickCount();
        FixedArr.SetSize(1000000); //サイズがわかっているとしたら
        t = GetTickCount() -t;
        sprintf(ch,"CStringArray(固定) SetSize 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            FixedArr.SetAt(ii,"str");
        }
        t = GetTickCount() -t;
        sprintf(ch,"CStringArray(固定)::SetAt 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = FixedArr.GetAt(ii);
        }
        t = GetTickCount() -t;
        sprintf(ch,"CStringArray(固定)::GetAt 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //---------------------------------------------------
        // Testクラス サイズ未設定
        //---------------------------------------------------
        Test* clsT = NULL;
        t = GetTickCount();
        clsT = new Test[1000000];
        t = GetTickCount() -t;
        sprintf(ch,"Testクラス new1000000 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //set Test
        t = GetTickCount();  for( ii = 0; ii < 1000000 ; ii++ )
        {
            memset( clsT[ii].aaa,0,sizeof(clsT[ii].aaa) );
            memcpy( clsT[ii].aaa,"str",3);
        }
        t = GetTickCount() -t;
        sprintf(ch,"Testクラス set 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = clsT[ii].aaa;
        }
        t = GetTickCount() -t;
        sprintf(ch,"Testクラス get 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
        t = GetTickCount();
        delete [] clsT;
        t = GetTickCount() -t;
        sprintf(ch,"Testクラス delete 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //---------------------------------------------------
        // Test2クラス サイズ未設定
        //---------------------------------------------------
        Test2* clsT2 = NULL;
        t = GetTickCount();
        clsT2 = new Test2[1000000];
        t = GetTickCount() -t;
    
        sprintf(ch,"Test2クラス(メンバ:CString) new1000000 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //set Test
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            clsT2[ii].aaa="str";
        }
        t = GetTickCount() -t;
        sprintf(ch,"Test2クラス(メンバ:CString) set 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = clsT2[ii].aaa;
        }
        t = GetTickCount() -t;
        sprintf(ch,"Test2クラス(メンバ:CString) get 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
        t = GetTickCount();
        delete [] clsT2;
        t = GetTickCount() -t;
        sprintf(ch,"Test2クラス(メンバ:CString) delete 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //---------------------------------------------------
        // 構造体 サイズ未設定
        //---------------------------------------------------
        STRACT* st = NULL;
        t = GetTickCount();
        st = new STRACT[1000000];
        t = GetTickCount() -t;
        sprintf(ch,"構造体 new1000000 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
    
        //set Test
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            memset( st[ii].str,0,sizeof(st[ii].str) );
            memcpy( st[ii].str,"str",3);
        }
        t = GetTickCount() -t;
        sprintf(ch,"構造体 set 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
        //get CMap
        t = GetTickCount();
        for( ii = 0; ii < 1000000 ; ii++ )
        {
            str = st[ii].str;
        }
        t = GetTickCount() -t;
        sprintf(ch,"構造体 get 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
        t = GetTickCount();
        delete [] st;
    
        t = GetTickCount() -t;
        sprintf(ch,"構造体 delete 処理時間[%ld]ミリ秒\r\n",t);
        printf("%s",ch);
        _getch();
        return 0;
    }
    結果:
    
    CMap set 処理時間[131665]ミリ秒
    CMap get 処理時間[128747]ミリ秒
    CStringArray::Add 処理時間[2543]ミリ秒
    CStringArray::GetAt 処理時間[63]ミリ秒
    CStringArray(固定) SetSize 処理時間[31]ミリ秒
    CStringArray(固定)::SetAt 処理時間[483]ミリ秒
    CStringArray(固定)::GetAt 処理時間[63]ミリ秒
    Testクラス new1000000 処理時間[0]ミリ秒
    Testクラス set 処理時間[265]ミリ秒
    Testクラス get 処理時間[234]ミリ秒
    Testクラス delete 処理時間[16]ミリ秒
    Test2クラス(メンバ:CString) new1000000 処理時間[46]ミリ秒
    Test2クラス(メンバ:CString) set 処理時間[375]ミリ秒
    Test2クラス(メンバ:CString) get 処理時間[62]ミリ秒
    Test2クラス(メンバ:CString) delete 処理時間[94]ミリ秒
    構造体 new1000000 処理時間[0]ミリ秒
    構造体 set 処理時間[203]ミリ秒
    構造体 get 処理時間[218]ミリ秒
    構造体 delete 処理時間[31]ミリ秒
    

    (デバッグモードではもうちょい遅いので、計測するならちゃんとexe作ってexeを実行すること)

    結論として、シーケンシャルアクセスするんだったらCMapよりもCStringArrayの方が速い。 CMapの利点はダイレクトアクセスであって、シーケンシャルアクセスには向いていない。 で、件数があらかじめわかってるなら、CStringArray::Addよりも SetSize ⇒ SetAt の方が早い。 もっというなら、やっぱりネイティブに作った方が早い。

    関連記事

    ページ上部へ戻る