From: khizmax Date: Sun, 22 Nov 2015 09:06:39 +0000 (+0300) Subject: Added new test for bounded queues X-Git-Tag: v2.1.0~58 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=32fcef06e5bb8af0f3804a07c6555bcd484d0e2a;p=libcds.git Added new test for bounded queues --- diff --git a/projects/Win/vc12/unit-queue.vcxproj b/projects/Win/vc12/unit-queue.vcxproj index 103c41e9..639c3c05 100644 --- a/projects/Win/vc12/unit-queue.vcxproj +++ b/projects/Win/vc12/unit-queue.vcxproj @@ -490,6 +490,7 @@ + diff --git a/projects/Win/vc14/unit-queue.vcxproj b/projects/Win/vc14/unit-queue.vcxproj index bf32217d..574d06ce 100644 --- a/projects/Win/vc14/unit-queue.vcxproj +++ b/projects/Win/vc14/unit-queue.vcxproj @@ -581,6 +581,7 @@ + diff --git a/projects/source.unit.queue.mk b/projects/source.unit.queue.mk index 7c677e00..0c80d48d 100644 --- a/projects/source.unit.queue.mk +++ b/projects/source.unit.queue.mk @@ -1,5 +1,6 @@ CDSUNIT_QUEUE_SOURCES := \ + tests/unit/queue/bounded_queue_fulness.cpp \ tests/unit/queue/queue_pop.cpp \ tests/unit/queue/queue_push.cpp \ tests/unit/queue/queue_random.cpp \ diff --git a/tests/data/test-debug.conf b/tests/data/test-debug.conf index ce46294d..6b9e4444 100644 --- a/tests/data/test-debug.conf +++ b/tests/data/test-debug.conf @@ -99,6 +99,11 @@ QueueSize=100000 ThreadCount=4 QueueSize=500000 +[BoundedQueue_Fullness] +ThreadCount=4 +QueueSize=1024 +PassCount=100000 + [PQueue_Push] ThreadCount=4 QueueSize=10000 diff --git a/tests/data/test-express.conf b/tests/data/test-express.conf index c58393c8..6f9b2f55 100644 --- a/tests/data/test-express.conf +++ b/tests/data/test-express.conf @@ -100,9 +100,10 @@ QueueSize=500000 ThreadCount=8 QueueSize=500000 -[Queue_bounded_empty_ST] -PassCount=100 -QueueSize=256 +[BoundedQueue_Fullness] +ThreadCount=4 +QueueSize=1024 +PassCount=100000 [PQueue_Push] ThreadCount=8 diff --git a/tests/data/test.conf b/tests/data/test.conf index f0d175db..2d35bd01 100644 --- a/tests/data/test.conf +++ b/tests/data/test.conf @@ -99,6 +99,11 @@ QueueSize=5000000 ThreadCount=8 QueueSize=5000000 +[BoundedQueue_Fullness] +ThreadCount=8 +QueueSize=1024 +PassCount=1000000 + [PQueue_Push] ThreadCount=8 QueueSize=10000000 diff --git a/tests/unit/queue/CMakeLists.txt b/tests/unit/queue/CMakeLists.txt index 82eafd2a..b32e7123 100644 --- a/tests/unit/queue/CMakeLists.txt +++ b/tests/unit/queue/CMakeLists.txt @@ -1,6 +1,7 @@ set(PACKAGE_NAME cdsu-queue) set(CDSUNIT_QUEUE_SOURCES + bounded_queue_fulness.cpp queue_pop.cpp queue_push.cpp queue_random.cpp diff --git a/tests/unit/queue/bounded_queue_fulness.cpp b/tests/unit/queue/bounded_queue_fulness.cpp new file mode 100644 index 00000000..9222aaf8 --- /dev/null +++ b/tests/unit/queue/bounded_queue_fulness.cpp @@ -0,0 +1,193 @@ +//$$CDS-header$$ + +#include "cppunit/thread.h" +#include "queue/queue_type.h" +#include "queue/queue_defs.h" + + +/* + Bounded queue test. + The test checks the behaviour of bounded queue when it is almost full. + Many algorithms says the queue is full when it is not, and vice versa. +*/ +namespace queue { + +#define TEST_BOUNDED( Q, V ) void Q() { test< Types::Q >(); } + + namespace ns_BoundedQueue_Fullness { + static size_t s_nThreadCount = 8; + static size_t s_nQueueSize = 1024; + static size_t s_nPassCount = 1000000; + } + using namespace ns_BoundedQueue_Fullness; + + class BoundedQueue_Fullness: public CppUnitMini::TestCase + { + template + class Thread: public CppUnitMini::TestThread + { + virtual TestThread * clone() + { + return new Thread( *this ); + } + public: + Queue& m_Queue; + double m_fTime; + size_t m_nPushError; + size_t m_nPopError; + + public: + Thread( CppUnitMini::ThreadPool& pool, Queue& q ) + : CppUnitMini::TestThread( pool ) + , m_Queue( q ) + {} + Thread( Thread& src ) + : CppUnitMini::TestThread( src ) + , m_Queue( src.m_Queue ) + {} + + BoundedQueue_Fullness& getTest() + { + return reinterpret_cast( m_Pool.m_Test ); + } + + virtual void init() + { + cds::threading::Manager::attachThread(); + } + virtual void fini() + { + cds::threading::Manager::detachThread(); + } + + virtual void test() + { + m_fTime = m_Timer.duration(); + + m_nPushError = 0; + m_nPopError = 0; + for ( size_t i = 0; i < s_nPassCount; ++i ) { + if ( !m_Queue.push( i )) + ++m_nPushError; + size_t item; + if ( !m_Queue.pop( item )) + ++m_nPopError; + } + m_fTime = m_Timer.duration() - m_fTime; + } + }; + + protected: + template + void analyze( CppUnitMini::ThreadPool& pool, Queue& testQueue ) + { + double fTime = 0; + size_t nPushError = 0; + size_t nPopError = 0; + for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { + Thread * pThread = reinterpret_cast *>(*it); + fTime += pThread->m_fTime; + nPushError += pThread->m_nPushError; + nPopError += pThread->m_nPopError; + } + CPPUNIT_MSG( " Duration=" << (fTime / s_nThreadCount) ); + CPPUNIT_MSG( " Errors: push=" << nPushError << ", pop=" << nPopError ); + CPPUNIT_CHECK( !testQueue.empty()); + CPPUNIT_CHECK( nPushError == 0 ); + CPPUNIT_CHECK( nPopError == 0 ); + } + + template + void test() + { + Queue testQueue; + + CppUnitMini::ThreadPool pool( *this ); + pool.add( new Thread( pool, testQueue ), s_nThreadCount ); + + size_t nSize = testQueue.capacity() - s_nThreadCount; + for ( size_t i = 0; i < nSize; ++i ) + testQueue.push( i ); + + CPPUNIT_MSG( " Thread count=" << s_nThreadCount << " ..."); + pool.run(); + + analyze( pool, testQueue ); + + CPPUNIT_MSG( testQueue.statistics() ); + } + + template + void test_bounded() + { + size_t nStart = 0; + size_t nThreadItemCount = s_nQueueSize / s_nThreadCount; + + Queue testQueue( s_nQueueSize ); + + CppUnitMini::ThreadPool pool( *this ); + pool.add( new Thread( pool, testQueue ), s_nThreadCount ); + + for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { + Thread * pThread = reinterpret_cast *>(*it); + pThread->m_nStartItem = nStart; + nStart += nThreadItemCount; + pThread->m_nEndItem = nStart; + } + + CPPUNIT_MSG( " Push test, thread count=" << s_nThreadCount << " ..."); + pool.run(); + + analyze( pool, testQueue ); + + CPPUNIT_MSG( testQueue.statistics() ); + } + + template + void test_segmented() + { + CPPUNIT_MSG( " Push test, thread count=" << s_nThreadCount << " ..."); + for ( size_t nSegmentSize = 4; nSegmentSize <= 256; nSegmentSize *= 4 ) { + CPPUNIT_MSG( "Segment size: " << nSegmentSize ); + + Queue testQueue( nSegmentSize ); + + CppUnitMini::ThreadPool pool( *this ); + pool.add( new Thread( pool, testQueue ), s_nThreadCount ); + + size_t nStart = 0; + size_t nThreadItemCount = s_nQueueSize / s_nThreadCount; + for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) { + Thread * pThread = reinterpret_cast *>(*it); + pThread->m_nStartItem = nStart; + nStart += nThreadItemCount; + pThread->m_nEndItem = nStart; + } + + pool.run(); + + analyze( pool, testQueue ); + + CPPUNIT_MSG( testQueue.statistics() ); + } + } + + void setUpParams( const CppUnitMini::TestCfg& cfg ) { + s_nThreadCount = cfg.getULong("ThreadCount", 8 ); + s_nQueueSize = cfg.getULong("QueueSize", 1024 ); + s_nPassCount = cfg.getULong( "PassCount", 1000000 ); + } + + protected: + CDSUNIT_DECLARE_TsigasCycleQueue( size_t ) + CDSUNIT_DECLARE_VyukovMPMCCycleQueue( size_t ) + + CPPUNIT_TEST_SUITE( BoundedQueue_Fullness ) + CDSUNIT_TEST_TsigasCycleQueue + CDSUNIT_TEST_VyukovMPMCCycleQueue + CPPUNIT_TEST_SUITE_END(); + }; + +} // namespace queue + +CPPUNIT_TEST_SUITE_REGISTRATION(queue::BoundedQueue_Fullness );