2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Linux scalability allocator test
33 #include "alloc/michael_allocator.h"
35 #include <cds/os/timer.h>
36 #include <cds/os/topology.h>
38 #include "cppunit/thread.h"
42 static size_t s_nPassCount = 10000000;
43 static size_t s_nMaxBlockSize = 64 * 1024 - 16;
44 static size_t s_nMaxThreadCount = 64;
46 static size_t s_nPassPerThread;
48 # define TEST_ALLOC(X, CLASS) void X() { test< CLASS >(false) ; }
49 # define TEST_ALLOC_STAT(X, CLASS) void X() { test< CLASS >(true) ; }
51 class Linux_Scale: public CppUnitMini::TestCase
53 template <class ALLOC>
54 class Thread: public CppUnitMini::TestThread
59 virtual Thread * clone()
61 return new Thread( *this );
66 Thread( CppUnitMini::ThreadPool& pool, ALLOC& a, size_t nSize )
67 : CppUnitMini::TestThread( pool )
72 : CppUnitMini::TestThread( src )
73 , m_Alloc( src.m_Alloc )
74 , m_nSize( src.m_nSize )
77 Linux_Scale& getTest()
79 return reinterpret_cast<Linux_Scale&>( m_Pool.m_Test );
82 virtual void init() { cds::threading::Manager::attachThread() ; }
83 virtual void fini() { cds::threading::Manager::detachThread() ; }
87 for ( size_t i = 0; i < s_nPassPerThread; ++i ) {
88 typename ALLOC::value_type * p = m_Alloc.allocate( m_nSize / sizeof( typename ALLOC::value_type ), nullptr );
89 CPPUNIT_ASSERT( p != nullptr );
91 memset( p, 0, m_nSize );
94 memset( ((char *)p) + m_nSize * sizeof(*p) - 16, 0, 16 );
96 CPPUNIT_ASSERT( (reinterpret_cast<uintptr_t>(p) & (ALLOC::alignment - 1)) == 0 );
97 m_Alloc.deallocate( p, 1 );
102 template <class ALLOC>
103 void test( size_t nThreadCount, size_t nSize )
105 cds::OS::Timer timer;
109 CPPUNIT_MSG( " Block size=" << nSize );
110 s_nPassPerThread = s_nPassCount / nThreadCount;
112 CppUnitMini::ThreadPool pool( *this );
113 pool.add( new Thread<ALLOC>( pool, alloc, nSize ), nThreadCount );
115 CPPUNIT_MSG( " Duration=" << pool.avgDuration() );
118 template <class ALLOC>
119 void test( size_t nThreadCount )
121 CPPUNIT_MSG( "Thread count=" << nThreadCount );
122 for ( size_t sz = 1; sz < s_nMaxBlockSize; sz *= 2 ) {
123 test<ALLOC>( nThreadCount, sz );
127 template <class ALLOC>
128 void test( bool bStat )
130 for ( size_t nThreadCount = 1; nThreadCount <= s_nMaxThreadCount; nThreadCount *= 2 ) {
131 summary_stat stBegin;
133 ALLOC::stat(stBegin);
135 test<ALLOC>( nThreadCount );
139 ALLOC::stat( stEnd );
141 std::cout << "\nStatistics:\n"
144 std::cout << "\nDelta statistics:\n"
150 void setUpParams( const CppUnitMini::TestCfg& cfg )
152 s_nPassCount = cfg.getULong( "PassCount", 10000000 );
153 s_nMaxBlockSize = cfg.getULong( "MaxBlockSize", 64 * 1024 - 16 );
154 s_nMaxThreadCount = cfg.getUInt( "MaxThreadCount", 64 );
155 if ( s_nMaxThreadCount == 0 )
156 s_nMaxThreadCount = cds::OS::topology::processor_count() * 2;
159 typedef MichaelAlignHeap_Stat<char, 64> t_MichaelAlignHeap_Stat;
160 typedef MichaelAlignHeap_NoStat<char,64> t_MichaelAlignHeap_NoStat;
161 typedef system_aligned_allocator<char, 64> t_system_aligned_allocator;
163 TEST_ALLOC_STAT( michael_heap_stat, MichaelHeap_Stat<char> )
164 TEST_ALLOC( michael_heap_nostat, MichaelHeap_NoStat<char> )
165 TEST_ALLOC( std_alloc, std_allocator<char> )
167 TEST_ALLOC_STAT( michael_alignheap_stat, t_MichaelAlignHeap_Stat )
168 TEST_ALLOC( michael_alignheap_nostat, t_MichaelAlignHeap_NoStat )
169 TEST_ALLOC( system_aligned_alloc, t_system_aligned_allocator )
171 CPPUNIT_TEST_SUITE( Linux_Scale )
172 CPPUNIT_TEST( michael_heap_nostat )
173 CPPUNIT_TEST( michael_heap_stat )
174 CPPUNIT_TEST( std_alloc )
176 CPPUNIT_TEST( system_aligned_alloc )
177 CPPUNIT_TEST( michael_alignheap_stat )
178 CPPUNIT_TEST( michael_alignheap_nostat )
179 CPPUNIT_TEST_SUITE_END();
182 } // namespace memory
183 CPPUNIT_TEST_SUITE_REGISTRATION( memory::Linux_Scale );