push.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright (c) 2006-2018 Maxim Khizhinsky
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include "pqueue_type.h"
  6. #include "item.h"
  7. namespace pqueue {
  8. static size_t s_nThreadCount = 8;
  9. static size_t s_nQueueSize = 2000000;
  10. class pqueue_push: public cds_test::stress_fixture
  11. {
  12. typedef cds_test::stress_fixture base_class;
  13. protected:
  14. template <class PQueue>
  15. class Producer: public cds_test::thread
  16. {
  17. typedef cds_test::thread base_class;
  18. public:
  19. Producer( cds_test::thread_pool& pool, PQueue& queue )
  20. : base_class( pool )
  21. , m_Queue( queue )
  22. {}
  23. Producer( Producer& src )
  24. : base_class( src )
  25. , m_Queue( src.m_Queue )
  26. {}
  27. virtual thread * clone()
  28. {
  29. return new Producer( *this );
  30. }
  31. virtual void test()
  32. {
  33. typedef typename PQueue::value_type value_type;
  34. for ( auto it = m_arr.begin(); it != m_arr.end(); ++it ) {
  35. if ( !m_Queue.push( value_type( *it )))
  36. ++m_nPushError;
  37. }
  38. }
  39. void prepare( size_t nStart, size_t nEnd )
  40. {
  41. m_arr.reserve( nEnd - nStart );
  42. for ( size_t i = nStart; i < nEnd; ++i )
  43. m_arr.push_back( i );
  44. shuffle( m_arr.begin(), m_arr.end());
  45. }
  46. public:
  47. PQueue& m_Queue;
  48. size_t m_nPushError = 0;
  49. std::vector<size_t> m_arr;
  50. };
  51. protected:
  52. template <class PQueue>
  53. void analyze( PQueue& q )
  54. {
  55. cds_test::thread_pool& pool = get_pool();
  56. for ( size_t i = 0; i < pool.size(); ++i ) {
  57. Producer<PQueue>& prod = static_cast<Producer<PQueue>&>(pool.get( i ));
  58. EXPECT_EQ( prod.m_nPushError, 0u ) << "producer=" << i;
  59. }
  60. EXPECT_FALSE( q.empty());
  61. typedef std::vector<size_t> vector_type;
  62. vector_type arr;
  63. arr.reserve( s_nQueueSize );
  64. size_t nPopped = 0;
  65. typename PQueue::value_type val;
  66. while ( q.pop( val )) {
  67. nPopped++;
  68. arr.push_back( val.key );
  69. }
  70. EXPECT_EQ( arr.size(), s_nQueueSize );
  71. auto it = arr.begin();
  72. size_t nPrev = *it;
  73. ++it;
  74. for ( auto itEnd = arr.end(); it != itEnd; ++it ) {
  75. EXPECT_EQ( nPrev - 1, *it );
  76. nPrev = *it;
  77. }
  78. }
  79. template <class PQueue>
  80. void test( PQueue& q )
  81. {
  82. cds_test::thread_pool& pool = get_pool();
  83. pool.add( new Producer<PQueue>( pool, q ), s_nThreadCount );
  84. size_t nStart = 0;
  85. size_t nThreadItemCount = s_nQueueSize / s_nThreadCount;
  86. s_nQueueSize = nThreadItemCount * s_nThreadCount;
  87. for ( size_t i = 0; i < pool.size(); ++i ) {
  88. static_cast<Producer<PQueue>&>(pool.get( i )).prepare( nStart, nStart + nThreadItemCount );
  89. nStart += nThreadItemCount;
  90. }
  91. propout() << std::make_pair( "thread_count", s_nThreadCount )
  92. << std::make_pair( "push_count", s_nQueueSize );
  93. std::chrono::milliseconds duration = pool.run();
  94. propout() << std::make_pair( "duration", duration );
  95. analyze( q );
  96. propout() << q.statistics();
  97. }
  98. public:
  99. static void SetUpTestCase()
  100. {
  101. cds_test::config const& cfg = get_config( "pqueue_push" );
  102. s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
  103. s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );
  104. if ( s_nThreadCount == 0u )
  105. s_nThreadCount = 1;
  106. if ( s_nQueueSize == 0u )
  107. s_nQueueSize = 1000;
  108. }
  109. //static void TearDownTestCase();
  110. };
  111. #define CDSSTRESS_MSPriorityQueue( fixture_t, pqueue_t ) \
  112. TEST_F( fixture_t, pqueue_t ) \
  113. { \
  114. typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
  115. pqueue_type pq( s_nQueueSize ); \
  116. test( pq ); \
  117. }
  118. CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_dyn_less )
  119. CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_dyn_less_stat )
  120. CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_dyn_cmp )
  121. //CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_dyn_mutex ) // too slow
  122. #define CDSSTRESS_MSPriorityQueue_static( fixture_t, pqueue_t ) \
  123. TEST_F( fixture_t, pqueue_t ) \
  124. { \
  125. typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
  126. std::unique_ptr< pqueue_type > pq( new pqueue_type ); \
  127. test( *pq.get()); \
  128. }
  129. //CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_static_less )
  130. //CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_static_less_stat )
  131. //CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_static_cmp )
  132. //CDSSTRESS_MSPriorityQueue( pqueue_push, MSPriorityQueue_static_mutex )
  133. #define CDSSTRESS_PriorityQueue( fixture_t, pqueue_t ) \
  134. TEST_F( fixture_t, pqueue_t ) \
  135. { \
  136. typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
  137. pqueue_type pq; \
  138. test( pq ); \
  139. }
  140. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_vector )
  141. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_vector_stat )
  142. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_deque )
  143. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_deque_stat )
  144. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_boost_deque )
  145. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_boost_deque_stat )
  146. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_boost_stable_vector )
  147. CDSSTRESS_PriorityQueue( pqueue_push, FCPQueue_boost_stable_vector_stat )
  148. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_HP_max )
  149. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_HP_max_stat )
  150. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_HP_min )
  151. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_HP_min_stat )
  152. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_DHP_max )
  153. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_DHP_max_stat )
  154. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_DHP_min )
  155. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_DHP_min_stat )
  156. // CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpi_max )
  157. // CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpi_max_stat )
  158. // CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpi_min )
  159. // CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpi_min_stat )
  160. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpb_max )
  161. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpb_max_stat )
  162. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpb_min )
  163. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpb_min_stat )
  164. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpt_max )
  165. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpt_max_stat )
  166. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpt_min )
  167. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_gpt_min_stat )
  168. #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
  169. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_shb_max )
  170. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_shb_max_stat )
  171. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_shb_min )
  172. CDSSTRESS_PriorityQueue( pqueue_push, EllenBinTree_RCU_shb_min_stat )
  173. #endif
  174. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_HP_max )
  175. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_HP_max_stat )
  176. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_HP_min )
  177. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_HP_min_stat )
  178. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_DHP_max )
  179. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_DHP_max_stat )
  180. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_DHP_min )
  181. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_DHP_min_stat )
  182. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpi_max )
  183. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpi_min )
  184. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpb_max )
  185. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpb_min )
  186. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpt_max )
  187. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_gpt_min )
  188. #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
  189. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_shb_max )
  190. CDSSTRESS_PriorityQueue( pqueue_push, SkipList32_RCU_shb_min )
  191. #endif
  192. CDSSTRESS_PriorityQueue( pqueue_push, StdPQueue_vector_spin )
  193. CDSSTRESS_PriorityQueue( pqueue_push, StdPQueue_vector_mutex )
  194. CDSSTRESS_PriorityQueue( pqueue_push, StdPQueue_deque_spin )
  195. CDSSTRESS_PriorityQueue( pqueue_push, StdPQueue_deque_mutex )
  196. } // namespace queue