|
|
//+-------------------------------------------------------------
//
// 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.
}
|