/* * Тест для замера скорости работы подсчета ссылок на основе * Mutex-а и на основе Atomic-операций. */ #include #include #include #include #include #include #include #include #include class object_with_refcount_t { public : virtual ~object_with_refcount_t(); virtual void inc_ref_count() = 0; virtual void dec_ref_count() = 0; }; object_with_refcount_t::~object_with_refcount_t() {} // Реализация подсчета ссылок на основе Thread_Mutex. class refcount_by_mutex_t : public object_with_refcount_t { public : refcount_by_mutex_t(); virtual ~refcount_by_mutex_t(); virtual void inc_ref_count(); virtual void dec_ref_count(); private : typedef ACE_Guard< ACE_Thread_Mutex > guard_t; ACE_Thread_Mutex m_lock_1; ACE_Thread_Mutex m_lock_2; unsigned long m_c1; unsigned long m_c2; unsigned long m_c3; unsigned long m_c4; }; refcount_by_mutex_t::refcount_by_mutex_t() {} refcount_by_mutex_t::~refcount_by_mutex_t() {} void refcount_by_mutex_t::inc_ref_count() { { guard_t guard( m_lock_1 ); ++m_c1; ++m_c2; } { guard_t guard( m_lock_2 ); ++m_c3; ++m_c4; } } void refcount_by_mutex_t::dec_ref_count() { { guard_t guard( m_lock_1 ); --m_c2; --m_c1; } { guard_t guard( m_lock_2 ); --m_c4; --m_c3; } } // Реализация подсчета ссылок на основе Atomic_Op. class refcount_by_atomic_op_t : public object_with_refcount_t { public : refcount_by_atomic_op_t(); virtual ~refcount_by_atomic_op_t(); virtual void inc_ref_count(); virtual void dec_ref_count(); private : typedef ACE_Atomic_Op< ACE_Thread_Mutex, unsigned long > holder_t; holder_t m_c1; holder_t m_c2; holder_t m_c3; holder_t m_c4; }; refcount_by_atomic_op_t::refcount_by_atomic_op_t() {} refcount_by_atomic_op_t::~refcount_by_atomic_op_t() {} void refcount_by_atomic_op_t::inc_ref_count() { ++m_c1; ++m_c2; ++m_c3; ++m_c4; } void refcount_by_atomic_op_t::dec_ref_count() { --m_c4; --m_c3; --m_c2; --m_c1; } // Реализация подсчета ссылок на основе TSS. class refcount_by_tss_t : public object_with_refcount_t { public : refcount_by_tss_t(); virtual ~refcount_by_tss_t(); virtual void inc_ref_count(); virtual void dec_ref_count(); private : typedef ACE_TSS< ACE_TSS_Type_Adapter< unsigned long > > holder_t; holder_t m_c1; holder_t m_c2; holder_t m_c3; holder_t m_c4; }; refcount_by_tss_t::refcount_by_tss_t() {} refcount_by_tss_t::~refcount_by_tss_t() {} void refcount_by_tss_t::inc_ref_count() { ++(*m_c1); ++(*m_c2); ++(*m_c3); ++(*m_c4); } void refcount_by_tss_t::dec_ref_count() { --(*m_c4); --(*m_c3); --(*m_c2); --(*m_c1); } struct bench_data_t { object_with_refcount_t * m_object; unsigned int m_cycles; bench_data_t( object_with_refcount_t * object, unsigned int cycles ) : m_object( object ) , m_cycles( cycles ) {} }; ACE_THR_FUNC_RETURN work_thread( void * param ) { bench_data_t * bench = reinterpret_cast< bench_data_t * >( param ); for( unsigned int i = 0; i != bench->m_cycles; ) { bench->m_object->inc_ref_count(); ++i; bench->m_object->dec_ref_count(); } return 0; } template< class OBJECT > void bench( unsigned int object_count, unsigned int thread_per_object, unsigned int cycles ) { std::vector< bench_data_t > bench_data; unsigned int i; for( i = 0; i != object_count; ++i ) bench_data.push_back( bench_data_t( new OBJECT(), cycles ) ); for( i = 0; i != object_count; ++i ) { int rc = ACE_Thread_Manager::instance()->spawn_n( thread_per_object, work_thread, &bench_data[ i ] ); if( -1 == rc ) ACE_OS::perror( "unable to spawn threads!" ); } ACE_Thread_Manager::instance()->wait(); for( i = 0; i != object_count; ++i ) delete bench_data[ i ].m_object; } template< class OBJECT > void run_and_measure( const char * test_name, unsigned int object_count, unsigned int thread_per_object, unsigned int cycles ) { ACE_Time_Value start = ACE_OS::gettimeofday(); bench< OBJECT >( object_count, thread_per_object, cycles ); ACE_Time_Value finish = ACE_OS::gettimeofday(); std::cout << test_name << ": " << ( finish.msec() - start.msec() ) / 1000.0 << std::endl; } int main( int argc, char ** argv ) { unsigned int object_count = 1; unsigned int thread_per_object = 8; unsigned int cycles = 1000000; if( argc > 1 ) { if( argc >= 2 ) { object_count = ACE_OS::atoi( argv[ 1 ] ); if( argc >= 3 ) { thread_per_object = ACE_OS::atoi( argv[ 2 ] ); if( argc == 4 ) cycles = ACE_OS::atoi( argv[ 3 ] ); } } } std::cout << "objects: " << object_count << ", thread_per_object: " << thread_per_object << ", cycles: " << cycles << std::endl; run_and_measure< refcount_by_mutex_t >( "refcount_by_mutex", object_count, thread_per_object, cycles ); run_and_measure< refcount_by_atomic_op_t >( "refcount_by_atomic_op", object_count, thread_per_object, cycles ); run_and_measure< refcount_by_tss_t >( "refcount_by_tss", object_count, thread_per_object, cycles ); return 0; }