550 lines
14 KiB
C++
550 lines
14 KiB
C++
//+-------------------------------------------------------------
|
||
//
|
||
// File: perfcli.cxx
|
||
//
|
||
// Contents: First attempt at getting perfcliing to work
|
||
//
|
||
// This is the client side
|
||
//
|
||
//
|
||
//---------------------------------------------------------------
|
||
|
||
#include <windows.h>
|
||
#include <stdio.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <errno.h>
|
||
#include <io.h>
|
||
|
||
#include <ole2.h>
|
||
#include "iperf.h"
|
||
#include "..\perfsrv\perfsrv.hxx"
|
||
#include <memalloc.h>
|
||
|
||
#pragma hdrstop
|
||
|
||
#define TEST_FILE L"\\tmp\\test"
|
||
|
||
void QueryMsg( void );
|
||
|
||
// These are Cairo symbols. Just define them here so I don't have to rip
|
||
// out or conditionally compile all references to them.
|
||
#define COINIT_MULTITHREADED 0
|
||
#define COINIT_SINGLETHREADED 1
|
||
|
||
DWORD thread_mode = COINIT_SINGLETHREADED;
|
||
int num_objects = 1;
|
||
int num_iterations = 1000;
|
||
HANDLE helper_wait;
|
||
HANDLE main_wait;
|
||
|
||
/*************************************************************************/
|
||
int DoTest()
|
||
{
|
||
IPerf **perf;
|
||
HRESULT result;
|
||
DWORD time_first;
|
||
DWORD waste;
|
||
int i;
|
||
int j;
|
||
BOOL success;
|
||
LARGE_INTEGER frequency;
|
||
LARGE_INTEGER count_first;
|
||
LARGE_INTEGER count_last;
|
||
LARGE_INTEGER dummy;
|
||
|
||
// Allocate memory to hold the object and interface pointers.
|
||
perf = (IPerf **) malloc( sizeof(void *) * num_objects );
|
||
if (perf == NULL)
|
||
{
|
||
printf( "Could not get memory.\n" );
|
||
return 1;
|
||
}
|
||
|
||
// Get a test object.
|
||
result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
|
||
(void **) &perf[0] );
|
||
if (!SUCCEEDED(result))
|
||
{
|
||
printf( "Could not create instance of performance server: %x\n", result );
|
||
return 1;
|
||
}
|
||
|
||
// Create the required number of objects.
|
||
for (i = 1; i < num_objects; i++)
|
||
{
|
||
result = perf[0]->GetAnotherObject( &perf[i] );
|
||
if (!SUCCEEDED(result))
|
||
{
|
||
printf( "Could not get enough objects: 0x%x\n", result );
|
||
return 1;
|
||
}
|
||
perf[i]->NullCall();
|
||
}
|
||
|
||
// Prompt to start when the user is ready.
|
||
// printf( "Ready? " );
|
||
// gets( s );
|
||
|
||
// Compute the time spent just looping.
|
||
waste = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
;
|
||
waste = GetTickCount() - waste;
|
||
|
||
// Repeatedly call the first object to time it.
|
||
time_first = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
perf[0]->NullCall();
|
||
time_first = GetTickCount() - time_first - waste;
|
||
|
||
// Print the results.
|
||
printf( "%d uS/Call\n", time_first*1000/num_iterations );
|
||
|
||
/*
|
||
// Measure the same thing using the performance counter.
|
||
success = QueryPerformanceFrequency( &frequency );
|
||
if (!success)
|
||
{
|
||
printf( "Could not query performance frequency.\n" );
|
||
goto free;
|
||
}
|
||
success = QueryPerformanceCounter( &count_first );
|
||
if (!success)
|
||
{
|
||
printf( "Could not query performance counter.\n" );
|
||
goto free;
|
||
}
|
||
perf[0]->NullCall();
|
||
success = QueryPerformanceCounter( &count_last );
|
||
if (!success)
|
||
{
|
||
printf( "Could not query performance counter.\n" );
|
||
goto free;
|
||
}
|
||
if (count_last.HighPart != count_first.HighPart ||
|
||
frequency.HighPart != 0)
|
||
printf( "\n\n***** Overflow *****\n\n\n" );
|
||
count_last.LowPart = (count_last.LowPart - count_first.LowPart) * 1000000 /
|
||
frequency.LowPart;
|
||
printf( "\nFrequency %d\n", frequency.LowPart );
|
||
printf( "%d uS/Call\n", count_last.LowPart );
|
||
|
||
// How long does it take to query the performance counter?
|
||
success = QueryPerformanceCounter( &count_first );
|
||
if (!success)
|
||
{
|
||
printf( "Could not query performance counter.\n" );
|
||
goto free;
|
||
}
|
||
for (i = 0; i < num_iterations; i++)
|
||
QueryPerformanceCounter( &dummy );
|
||
success = QueryPerformanceCounter( &count_last );
|
||
if (!success)
|
||
{
|
||
printf( "Could not query performance counter.\n" );
|
||
goto free;
|
||
}
|
||
if (count_last.HighPart != count_first.HighPart ||
|
||
frequency.HighPart != 0)
|
||
printf( "\n\n***** Overflow *****\n\n\n" );
|
||
count_last.LowPart = (count_last.LowPart - count_first.LowPart) /
|
||
num_iterations * 1000000 / frequency.LowPart;
|
||
printf( "%d uS/Query\n", count_last.LowPart );
|
||
*/
|
||
|
||
// Prompt to let the user peruse the results.
|
||
// printf( "Done? " );
|
||
// gets( s );
|
||
|
||
// Free the objects.
|
||
free:
|
||
for (i = 0; i < num_objects; i++)
|
||
perf[i]->Release();
|
||
return 0;
|
||
}
|
||
|
||
/*************************************************************************/
|
||
void EventTest()
|
||
{
|
||
DWORD time_first;
|
||
DWORD waste;
|
||
int i;
|
||
HANDLE helper;
|
||
|
||
// Measure how long it takes to loop.
|
||
waste = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
;
|
||
waste = GetTickCount() - waste;
|
||
|
||
// Measure how long it takes to get an event
|
||
time_first = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
{
|
||
helper = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||
if (helper == NULL)
|
||
{
|
||
printf( "Could not create event %d.\n", i );
|
||
return;
|
||
}
|
||
CloseHandle( helper );
|
||
}
|
||
time_first = GetTickCount() - time_first - waste;
|
||
printf( "%d uS/CreateEvent\n", time_first*1000/num_iterations );
|
||
|
||
// Don't bother cleaning up.
|
||
}
|
||
|
||
/*************************************************************************/
|
||
/* Parse the arguments. */
|
||
BOOL parse( int argc, char *argv[] )
|
||
{
|
||
int i;
|
||
int len;
|
||
TCHAR buffer[80];
|
||
|
||
#if 0
|
||
// Look up the thread mode from the win.ini file.
|
||
len = GetProfileString( L"My Section", L"ThreadMode", L"MultiThreaded", buffer,
|
||
sizeof(buffer) );
|
||
if (lstrcmp(buffer, L"SingleThreaded") == 0)
|
||
thread_mode = COINIT_SINGLETHREADED;
|
||
else if (lstrcmp(buffer, L"MultiThreaded") == 0)
|
||
thread_mode = COINIT_MULTITHREADED;
|
||
#endif
|
||
|
||
// Parse each item, skip the command name
|
||
for (i = 1; i < argc; i++)
|
||
{
|
||
if (strcmp( argv[i], "Single" ) == 0)
|
||
thread_mode = COINIT_SINGLETHREADED;
|
||
else if (strcmp( argv[i], "Multi" ) == 0)
|
||
thread_mode = COINIT_MULTITHREADED;
|
||
else if (strcmp( argv[i], "-o" ) == 0)
|
||
{
|
||
if (argv[++i] == NULL)
|
||
{
|
||
printf( "You must include an object count after the -o option.\n" );
|
||
return FALSE;
|
||
}
|
||
sscanf( argv[i], "%d", &num_objects );
|
||
}
|
||
else if (strcmp( argv[i], "-i" ) == 0)
|
||
{
|
||
if (argv[++i] == NULL)
|
||
{
|
||
printf( "You must include an object count after the -i option.\n" );
|
||
return FALSE;
|
||
}
|
||
sscanf( argv[i], "%d", &num_iterations );
|
||
}
|
||
else
|
||
{
|
||
printf( "You don't know what you are doing!\n" );
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*************************************************************************/
|
||
void MarshalTest()
|
||
{
|
||
HANDLE file;
|
||
HRESULT result;
|
||
IMoniker *moniker;
|
||
IBindCtx *bindctx;
|
||
WCHAR *wide_name;
|
||
unsigned char *name;
|
||
int i;
|
||
IPerf *perf;
|
||
|
||
// Initialize OLE.
|
||
result = OleInitialize(NULL);
|
||
if (FAILED(result))
|
||
{
|
||
printf( "Could not initialize OLE: 0x%x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Create file.
|
||
file = CreateFile( TEST_FILE, 0, 0, NULL, CREATE_ALWAYS,
|
||
FILE_ATTRIBUTE_NORMAL, NULL );
|
||
if (file == INVALID_HANDLE_VALUE)
|
||
{
|
||
printf( "Could not create file." );
|
||
return;
|
||
}
|
||
|
||
// Create file moniker.
|
||
result = CreateFileMoniker( TEST_FILE, &moniker );
|
||
if (FAILED(result))
|
||
{
|
||
printf( "Could not create file moniker: 0x%x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Get a bind context.
|
||
result = CreateBindCtx( NULL, &bindctx );
|
||
if (FAILED(result))
|
||
{
|
||
printf( "Could not create bind context: 0x%x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Display name.
|
||
result = moniker->GetDisplayName( bindctx, NULL, &wide_name );
|
||
if (FAILED(result))
|
||
{
|
||
printf( "Could not get display name: 0x%x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Convert the string to ascii and print it.
|
||
name = (unsigned char *) wide_name;
|
||
i = 0;
|
||
while (wide_name[i] != 0)
|
||
name[i] = wide_name[i++];
|
||
name[i] = 0;
|
||
printf( "The moniker is called <%s>\n", name );
|
||
|
||
// Free string.
|
||
CoTaskMemFree( wide_name );
|
||
|
||
// Get a test object.
|
||
result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
|
||
(void **) &perf );
|
||
if (!SUCCEEDED(result))
|
||
{
|
||
printf( "Could not create instance of performance server: %x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Pass moniker to server.
|
||
result = perf->PassMoniker( moniker );
|
||
if (FAILED(result))
|
||
{
|
||
printf( "Could not give moniker to server: 0x%x\n", result );
|
||
return;
|
||
}
|
||
|
||
// Release everything.
|
||
CloseHandle( file );
|
||
moniker->Release();
|
||
bindctx->Release();
|
||
perf->Release();
|
||
OleUninitialize();
|
||
}
|
||
|
||
|
||
//+--------------------------------------------------------------
|
||
// Function: Main
|
||
//
|
||
// Synopsis: Executes the BasicBnd test
|
||
//
|
||
// Effects: None
|
||
//
|
||
//
|
||
// Returns: Exits with exit code 0 if success, 1 otherwise
|
||
//
|
||
// History: 05-Mar-92 Sarahj Created
|
||
//
|
||
//---------------------------------------------------------------
|
||
|
||
int _cdecl main(int argc, char *argv[])
|
||
{
|
||
BOOL initialized = FALSE;
|
||
HRESULT hresult = S_OK;
|
||
BOOL fFailed = FALSE;
|
||
|
||
// Parse the command line arguments.
|
||
if (!parse( argc, argv ))
|
||
return 0;
|
||
|
||
// Print the process id.
|
||
printf( "Hi, I am %x.\n", GetCurrentProcessId() );
|
||
|
||
// Time event creation.
|
||
// EventTest();
|
||
// return 1;
|
||
|
||
// Pass around monikers.
|
||
// MarshalTest();
|
||
|
||
// Measure message queue APIs.
|
||
// QueryMsg();
|
||
|
||
|
||
// Print the thread mode.
|
||
if (thread_mode == COINIT_SINGLETHREADED)
|
||
{
|
||
printf( "Measuring performance for the single threaded mode.\n" );
|
||
}
|
||
else
|
||
{
|
||
printf( "Measuring performance for the multithreaded mode.\n" );
|
||
}
|
||
|
||
// must be called before any other OLE API
|
||
hresult = OleInitialize(NULL);
|
||
|
||
if (FAILED(hresult))
|
||
{
|
||
printf("OleInitialize Failed with %lx\n", hresult);
|
||
goto exit_main;
|
||
}
|
||
initialized = TRUE;
|
||
|
||
if (fFailed = DoTest())
|
||
goto exit_main;
|
||
|
||
/*
|
||
// Uninitialize and rerun in the other thread mode.
|
||
OleUninitialize();
|
||
if (thread_mode == COINIT_SINGLETHREADED)
|
||
thread_mode = COINIT_MULTITHREADED;
|
||
else
|
||
thread_mode = COINIT_SINGLETHREADED;
|
||
|
||
// Print the thread mode.
|
||
if (thread_mode == COINIT_SINGLETHREADED)
|
||
printf( "Measuring performance for the single threaded mode.\n" );
|
||
else
|
||
printf( "Measuring performance for the multithreaded mode.\n" );
|
||
|
||
// must be called before any other OLE API
|
||
hresult = OleInitialize(NULL);
|
||
|
||
if (FAILED(hresult))
|
||
{
|
||
printf("OleInitialize Failed with %lx\n", hresult);
|
||
goto exit_main;
|
||
}
|
||
|
||
if (fFailed = DoTest())
|
||
goto exit_main;
|
||
*/
|
||
|
||
exit_main:
|
||
|
||
if (initialized)
|
||
OleUninitialize();
|
||
|
||
if (!fFailed)
|
||
{
|
||
printf("\nCairole: PASSED\n");
|
||
}
|
||
else
|
||
{
|
||
printf("\nCairole: FAILED\n");
|
||
}
|
||
|
||
return fFailed;
|
||
}
|
||
|
||
/*************************************************************************/
|
||
DWORD _stdcall MsgHelper( void *param )
|
||
{
|
||
int i;
|
||
|
||
// Alternately signal and wait on an event. Do it one time too many
|
||
// because the main thread calls once to let us get set up.
|
||
for (i = 0; i < num_iterations+1; i++)
|
||
{
|
||
WaitForSingleObject( helper_wait, INFINITE );
|
||
SetEvent( main_wait );
|
||
}
|
||
|
||
#define must_return_a_value return 0
|
||
must_return_a_value;
|
||
}
|
||
|
||
/*************************************************************************/
|
||
void QueryMsg()
|
||
{
|
||
DWORD time_first;
|
||
DWORD waste;
|
||
int i;
|
||
HANDLE helper;
|
||
DWORD thread_id;
|
||
|
||
// Create an event.
|
||
helper_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||
if (helper_wait == NULL)
|
||
{
|
||
printf( "Could not create event.\n" );
|
||
return;
|
||
}
|
||
main_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||
if (main_wait == NULL)
|
||
{
|
||
printf( "Could not create event.\n" );
|
||
return;
|
||
}
|
||
|
||
// Measure how long it takes to loop.
|
||
waste = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
;
|
||
waste = GetTickCount() - waste;
|
||
|
||
// Measure how long it takes to query the message queue.
|
||
time_first = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
GetQueueStatus( QS_ALLINPUT );
|
||
time_first = GetTickCount() - time_first - waste;
|
||
printf( "%d uS/GetQueueStatus\n", time_first*1000/num_iterations );
|
||
|
||
// Start a thread to wake up this one.
|
||
helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
|
||
&thread_id );
|
||
if (helper == NULL)
|
||
{
|
||
printf( "Could not create helper thread.\n" );
|
||
return;
|
||
}
|
||
|
||
// Call MsgWaitForMultipleObjects once to let the thread get started.
|
||
SetEvent( helper_wait );
|
||
MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
|
||
INFINITE, QS_ALLINPUT );
|
||
|
||
// Measure how long it takes to call MsgWaitForMultipleObjects.
|
||
time_first = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
{
|
||
SetEvent( helper_wait );
|
||
MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
|
||
INFINITE, QS_ALLINPUT );
|
||
}
|
||
time_first = GetTickCount() - time_first - waste;
|
||
printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
|
||
|
||
// Start a thread to wake up this one.
|
||
helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
|
||
&thread_id );
|
||
if (helper == NULL)
|
||
{
|
||
printf( "Could not create helper thread.\n" );
|
||
return;
|
||
}
|
||
|
||
// Let the thread get started.
|
||
SetEvent( helper_wait );
|
||
WaitForSingleObject( main_wait, INFINITE );
|
||
|
||
// Measure how long it takes to switch threads just using events.
|
||
time_first = GetTickCount();
|
||
for (i = 0; i < num_iterations; i++)
|
||
{
|
||
SetEvent( helper_wait );
|
||
WaitForSingleObject( main_wait, INFINITE );
|
||
}
|
||
time_first = GetTickCount() - time_first - waste;
|
||
printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
|
||
|
||
// Don't bother cleaning up.
|
||
}
|
||
|
||
|