- 2012-2-24
- Visual C++
仕事で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 の方が早い。 もっというなら、やっぱりネイティブに作った方が早い。