コンテナーとオブジェクトポインターのパフォーマンステスト

エントリー





この記事では、さまざまなデータ型へのさまざまなタイプのポインターを含むオブジェクトを(push_back)コンテナーに格納するパフォーマンステストについて説明します。 このテストは複雑で、オブジェクトへのポインターの作成、オブジェクトのコピー、コンテナーの充填、スマートポインターと標準の削除演算子を使用したオブジェクトに割り当てられたメモリの解放といった一般的なタスクを組み合わせます。 標準テンプレートライブラリの3つのコンテナ-ベクトル、リスト、デック、3種類のポインタ-std :: shared_ptr、std :: auto_ptr、および単純なポインタがテストされます。 テストデータ型(どのポインターが作成されるか)として、long、std :: string、char、任意のクラスを使用しました。



テストの説明





ソースコードはMS Visual Studio 2010で記述されており、ラムダ関数のコンパイラサポートが必要です。

いくつかのクラスに、データ型TypeへのポインターTの説明が含まれるようにします。 コンストラクターはオブジェクトを作成し、渡されたパラメーターで初期化します。 コピーコンストラクターは、指定されたオブジェクトのアドレスにある値、およびその名前と要件をコピーして、オブジェクトの寿命に関するメッセージをコンソールに表示します。



template< class T, typename Type > class test_type_and_smart_pointer { public: test_type_and_smart_pointer( std::string const& val, bool msg, Type type_val ) : _msg( msg ), _name( val ) { if( _msg ) std::cout << "created " << _name << std::endl; x.reset( new Type ); *x = type_val; } ~test_type_and_smart_pointer() { if( _msg ) std::cout << "deleted " << _name << std::endl; } test_type_and_smart_pointer(const test_type_and_smart_pointer & W) { if( W._msg ) std::cout << "copied " << W._name << std::endl; this->x.reset( new Type ); *(this->x) = *(Wx); this->_name = W._name; this->_msg = W._msg; } private: T x; bool _msg; std::string _name; };
      
      







テンプレートオプション:



test_type_and_smart_pointerクラスのメンバー:





タイプTypeへのポインターTが標準である場合、同様のクラスを作成してみましょう。



 template< class T, typename Type > class test_type_and_simple_pointer { public: test_type_and_simple_pointer( std::string const& val, bool msg, Type type_val ) : _msg( msg ), _name( val ) { if( _msg ) std::cout << "created " << _name << std::endl; x = new Type; *x = type_val; } ~test_type_and_simple_pointer() { delete x; if( _msg ) std::cout << "deleted " << _name << std::endl; } test_type_and_simple_pointer(const test_type_and_simple_pointer & W) { if( W._msg ) std::cout << "copied " << W._name << std::endl; this->x = new Type( *(Wx) ); this->_name = W._name; this->_msg = W._msg; } private: T x; bool _msg; std::string _name; };
      
      







次に、上記のオブジェクトを作成する関数が必要です。



 template< typename _Ptr, typename T, typename Container, bool msg > void test_smart_ptr( bool big_data, T val ) { using namespace std; test_type_and_smart_pointer< _Ptr, T > x( "a001", msg, val ); test_type_and_smart_pointer< _Ptr, T > x2( x ); Container cnt; cnt.push_back( x ); cnt.push_back( x2 ); if( big_data ) for( int i = 0; i <= 100; i++ ) { test_type_and_smart_pointer< _Ptr, T > xx( "a002", msg, val ); test_type_and_smart_pointer< _Ptr, T > xx2( xx ); cnt.push_back( xx ); cnt.push_back( xx2 ); } cnt.clear(); } template< typename T, typename Container, bool msg > void test_simple_ptr( bool big_data, T val ) { using namespace std; test_type_and_simple_pointer< T*, T> x( "b001", msg, val ); test_type_and_simple_pointer< T*, T> x2( x ); Container cnt; cnt.push_back( x ); cnt.push_back( x2 ); if( big_data ) for( int i = 0; i <= 100; i++ ) { test_type_and_simple_pointer< T*, T> xx( "b002", msg, val ); test_type_and_simple_pointer< T*, T> xx2( xx ); cnt.push_back( xx ); cnt.push_back( xx2 ); } cnt.clear(); }
      
      







たとえば、これらの関数は、オブジェクトへのポインターのペアを作成してコンテナーに配置するモードと、オブジェクトへのポインターを周期的に作成してコンテナーを埋めるモードの2つで動作します。

test_smart_ptrおよびtest_simple_ptr関数の実行にかかる時間は、_time_testによって測定されます。



 double _time_test( std::function< void() > test_func, unsigned int times ) { using namespace std; double start = 0, end = 0; start = GetTickCount(); for( unsigned int i = 0; i < times; i++ ) { test_func(); } end = GetTickCount() - start; //cout << "Elapsed ms: " << end << // " for " << times << " times " << endl; return end; }
      
      







必要なヘッダーファイル:



 #include "iostream" #include "string" #include "vector" #include "list" #include "deque " #include <Windows.h> #include "functional"
      
      







任意の型のオブジェクトとして、動的メモリ割り当てのない最も単純なクラスが使用されます。



 class some_obj { public: some_obj() { i = 90000; s = "1231231231231231231232"; d = 39482.27392; } ~some_obj() { } private: int i; std::string s; double d; };
      
      







それで、テストはどのように行われましたか。 72個のラムダ関数が記述されており、それぞれが完了時にヒープを元の状態に戻します。



 int main() { using namespace std; const long long_val = 900000000; const char ch = 'a'; const string str = "abc"; /////////////////////////////////////////////////////////////////////////////////////////////////////// auto f_01 = [&]() -> void { test_smart_ptr< shared_ptr< long >, long, vector< test_type_and_smart_pointer< shared_ptr< long >, long > >, false >( false, long_val ); }; auto f_02 = [&]() -> void { test_smart_ptr< shared_ptr< char >, char, vector< test_type_and_smart_pointer< shared_ptr< char >, char > >, false >( false, ch ); }; auto f_03 = [&]() -> void { test_smart_ptr< shared_ptr< string >, string, vector< test_type_and_smart_pointer< shared_ptr< string >, string > >, false >( false, str ); }; auto f_04 = [&]() -> void { some_obj x; test_smart_ptr< shared_ptr< some_obj >, some_obj, vector< test_type_and_smart_pointer< shared_ptr< some_obj >, some_obj > >, false >( false, x ); }; ... _time_test( f_01, 100000 ); _time_test( f_02, 100000 ); _time_test( f_03, 100000 ); _time_test( f_04, 100000 ); ... return 0; }
      
      







面倒なためメイン関数の完全なコードは提供されませんが、shared_ptrポインターのラムダ関数の最初のブロックによると、テンプレートパラメーターの組み合わせの一般的な傾向が表示されます。



各f_nn関数は15回実行され、測定結果は平均化されました(起動はスタジオの下からではなくリリースモードで行われました )。 最小経過時間、つまり 他の値は比例して与えられます。



試験結果





色は、すべてのコンテナの中で各タイプのポインタの最速のデータタイプ示します。







すべてのポインタータイプの中で各コンテナーの最速のデータタイプ:







すべてのタイプのデータとすべてのインジケーターを埋める最速のコンテナー:







学習するのに何が役立ちますか?





まず、テスト結果はどのコンテナがより速く充填されているかを示します。

第二に、典型的なタスクへのポインタが速度の比例した比率でどのように機能するかが明確です。



All Articles