Listing 3: A program that measures multithreaded performance using thread classes and class-specific new and delete
// main.cpp #include "ThreadPrivateHeapAllocated.h" #include <process.h> #include <iostream> using namespace std; static const int NUM_ALLOCS = 20000; static const int NUM_THREADS = 4; class ClassAllocatedFromProcessHeap { public: protected: char m_buffer[1024]; }; class ClassAllocatedFromPrivateHeap : public CThreadPrivateHeapAllocated { public: protected: char m_buffer[1024]; }; class CThread { public: CThread() { m_hThread = (HANDLE) _beginthreadex( NULL, // no security attributes 0, // default stack size threadFunc, // starting address (LPVOID) this, // argument to threadFunc CREATE_SUSPENDED, // create suspended (UINT*)&m_dwThreadID ); // [out] thread ID } virtual ~CThread() { CloseHandle( m_hThread ); } DWORD Start() { return ResumeThread( m_hThread ); } virtual DWORD ThreadMain()=0; HANDLE GetThreadHandle() { return m_hThread; } protected: static UINT _stdcall threadFunc( LPVOID lpControlledThread ) { CThread* pThread = reinterpret_cast<CThread*>(lpControlledThread); return pThread->ThreadMain(); } HANDLE m_hThread; DWORD m_dwThreadID; }; class CThreadUsingProcessHeap : public CThread { public: virtual DWORD ThreadMain() { for( int i=0; i<NUM_ALLOCS; i++ ) { ClassAllocatedFromProcessHeap* p = new ClassAllocatedFromProcessHeap; delete p; } // for return 0; } }; class CThreadUsingPrivateHeap : public CThread { public: CThreadUsingPrivateHeap() { m_hHeap = HeapCreate( HEAP_NO_SERIALIZE, 0x100000, 0 ); } virtual ~CThreadUsingPrivateHeap() { HeapDestroy( m_hHeap ); } virtual DWORD ThreadMain() { TlsSetValue( CThreadPrivateHeapAllocated::GetTlsIndex(), (LPVOID) m_hHeap ); for( int i=0; i<NUM_ALLOCS; i++ ) { ClassAllocatedFromPrivateHeap* p = new ClassAllocatedFromPrivateHeap; delete p; } // for return 0; } protected: HANDLE m_hHeap; }; int main(int argc, char* argv[]) { // Allocate a slot for thread-private heap handle. Let the // CThreadPrivateHeapAllocated class know which slot number // will be used... CThreadPrivateHeapAllocated::SetTlsIndex( TlsAlloc() ); DWORD dwStart=0, dwEnd=0; int i=0; // --------------------------------------------------------- // Do the test with single process heap... CThreadUsingProcessHeap threadUsingProcessHeap[ NUM_THREADS ]; HANDLE hThreadUsingProcessHeap[NUM_THREADS]; dwStart = GetTickCount(); for( i=0; i<NUM_THREADS; i++ ) { hThreadUsingProcessHeap[i] = threadUsingProcessHeap[i].GetThreadHandle(); threadUsingProcessHeap[i].Start(); } // for WaitForMultipleObjects( NUM_THREADS, hThreadUsingProcessHeap, TRUE, INFINITE ); dwEnd = GetTickCount(); cout << "Test using single process heap took " << dwEnd-dwStart << " ms." << endl; // --------------------------------------------------------- // Do the test with private heap per thread... CThreadUsingPrivateHeap threadUsingPrivateHeap[ NUM_THREADS ]; HANDLE hThreadUsingPrivateHeap[NUM_THREADS]; dwStart = GetTickCount(); for( i=0; i<NUM_THREADS; i++ ) { hThreadUsingPrivateHeap[i] = threadUsingPrivateHeap[i].GetThreadHandle(); threadUsingPrivateHeap[i].Start(); } // for WaitForMultipleObjects( NUM_THREADS, hThreadUsingPrivateHeap, TRUE, INFINITE ); dwEnd = GetTickCount(); cout << "Test using private heap per thread took " << dwEnd-dwStart << " ms." << endl; TlsFree( CThreadPrivateHeapAllocated::GetTlsIndex() ); return 0; }