Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

549 lines
14 KiB

  1. //+-------------------------------------------------------------
  2. //
  3. // File: perfcli.cxx
  4. //
  5. // Contents: First attempt at getting perfcliing to work
  6. //
  7. // This is the client side
  8. //
  9. //
  10. //---------------------------------------------------------------
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <errno.h>
  16. #include <io.h>
  17. #include <ole2.h>
  18. #include "iperf.h"
  19. #include "..\perfsrv\perfsrv.hxx"
  20. #include <memalloc.h>
  21. #pragma hdrstop
  22. #define TEST_FILE L"\\tmp\\test"
  23. void QueryMsg( void );
  24. // These are Cairo symbols. Just define them here so I don't have to rip
  25. // out or conditionally compile all references to them.
  26. #define COINIT_MULTITHREADED 0
  27. #define COINIT_SINGLETHREADED 1
  28. DWORD thread_mode = COINIT_SINGLETHREADED;
  29. int num_objects = 1;
  30. int num_iterations = 1000;
  31. HANDLE helper_wait;
  32. HANDLE main_wait;
  33. /*************************************************************************/
  34. int DoTest()
  35. {
  36. IPerf **perf;
  37. HRESULT result;
  38. DWORD time_first;
  39. DWORD waste;
  40. int i;
  41. int j;
  42. BOOL success;
  43. LARGE_INTEGER frequency;
  44. LARGE_INTEGER count_first;
  45. LARGE_INTEGER count_last;
  46. LARGE_INTEGER dummy;
  47. // Allocate memory to hold the object and interface pointers.
  48. perf = (IPerf **) malloc( sizeof(void *) * num_objects );
  49. if (perf == NULL)
  50. {
  51. printf( "Could not get memory.\n" );
  52. return 1;
  53. }
  54. // Get a test object.
  55. result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
  56. (void **) &perf[0] );
  57. if (!SUCCEEDED(result))
  58. {
  59. printf( "Could not create instance of performance server: %x\n", result );
  60. return 1;
  61. }
  62. // Create the required number of objects.
  63. for (i = 1; i < num_objects; i++)
  64. {
  65. result = perf[0]->GetAnotherObject( &perf[i] );
  66. if (!SUCCEEDED(result))
  67. {
  68. printf( "Could not get enough objects: 0x%x\n", result );
  69. return 1;
  70. }
  71. perf[i]->NullCall();
  72. }
  73. // Prompt to start when the user is ready.
  74. // printf( "Ready? " );
  75. // gets( s );
  76. // Compute the time spent just looping.
  77. waste = GetTickCount();
  78. for (i = 0; i < num_iterations; i++)
  79. ;
  80. waste = GetTickCount() - waste;
  81. // Repeatedly call the first object to time it.
  82. time_first = GetTickCount();
  83. for (i = 0; i < num_iterations; i++)
  84. perf[0]->NullCall();
  85. time_first = GetTickCount() - time_first - waste;
  86. // Print the results.
  87. printf( "%d uS/Call\n", time_first*1000/num_iterations );
  88. /*
  89. // Measure the same thing using the performance counter.
  90. success = QueryPerformanceFrequency( &frequency );
  91. if (!success)
  92. {
  93. printf( "Could not query performance frequency.\n" );
  94. goto free;
  95. }
  96. success = QueryPerformanceCounter( &count_first );
  97. if (!success)
  98. {
  99. printf( "Could not query performance counter.\n" );
  100. goto free;
  101. }
  102. perf[0]->NullCall();
  103. success = QueryPerformanceCounter( &count_last );
  104. if (!success)
  105. {
  106. printf( "Could not query performance counter.\n" );
  107. goto free;
  108. }
  109. if (count_last.HighPart != count_first.HighPart ||
  110. frequency.HighPart != 0)
  111. printf( "\n\n***** Overflow *****\n\n\n" );
  112. count_last.LowPart = (count_last.LowPart - count_first.LowPart) * 1000000 /
  113. frequency.LowPart;
  114. printf( "\nFrequency %d\n", frequency.LowPart );
  115. printf( "%d uS/Call\n", count_last.LowPart );
  116. // How long does it take to query the performance counter?
  117. success = QueryPerformanceCounter( &count_first );
  118. if (!success)
  119. {
  120. printf( "Could not query performance counter.\n" );
  121. goto free;
  122. }
  123. for (i = 0; i < num_iterations; i++)
  124. QueryPerformanceCounter( &dummy );
  125. success = QueryPerformanceCounter( &count_last );
  126. if (!success)
  127. {
  128. printf( "Could not query performance counter.\n" );
  129. goto free;
  130. }
  131. if (count_last.HighPart != count_first.HighPart ||
  132. frequency.HighPart != 0)
  133. printf( "\n\n***** Overflow *****\n\n\n" );
  134. count_last.LowPart = (count_last.LowPart - count_first.LowPart) /
  135. num_iterations * 1000000 / frequency.LowPart;
  136. printf( "%d uS/Query\n", count_last.LowPart );
  137. */
  138. // Prompt to let the user peruse the results.
  139. // printf( "Done? " );
  140. // gets( s );
  141. // Free the objects.
  142. free:
  143. for (i = 0; i < num_objects; i++)
  144. perf[i]->Release();
  145. return 0;
  146. }
  147. /*************************************************************************/
  148. void EventTest()
  149. {
  150. DWORD time_first;
  151. DWORD waste;
  152. int i;
  153. HANDLE helper;
  154. // Measure how long it takes to loop.
  155. waste = GetTickCount();
  156. for (i = 0; i < num_iterations; i++)
  157. ;
  158. waste = GetTickCount() - waste;
  159. // Measure how long it takes to get an event
  160. time_first = GetTickCount();
  161. for (i = 0; i < num_iterations; i++)
  162. {
  163. helper = CreateEvent( NULL, FALSE, FALSE, NULL );
  164. if (helper == NULL)
  165. {
  166. printf( "Could not create event %d.\n", i );
  167. return;
  168. }
  169. CloseHandle( helper );
  170. }
  171. time_first = GetTickCount() - time_first - waste;
  172. printf( "%d uS/CreateEvent\n", time_first*1000/num_iterations );
  173. // Don't bother cleaning up.
  174. }
  175. /*************************************************************************/
  176. /* Parse the arguments. */
  177. BOOL parse( int argc, char *argv[] )
  178. {
  179. int i;
  180. int len;
  181. TCHAR buffer[80];
  182. #if 0
  183. // Look up the thread mode from the win.ini file.
  184. len = GetProfileString( L"My Section", L"ThreadMode", L"MultiThreaded", buffer,
  185. sizeof(buffer) );
  186. if (lstrcmp(buffer, L"SingleThreaded") == 0)
  187. thread_mode = COINIT_SINGLETHREADED;
  188. else if (lstrcmp(buffer, L"MultiThreaded") == 0)
  189. thread_mode = COINIT_MULTITHREADED;
  190. #endif
  191. // Parse each item, skip the command name
  192. for (i = 1; i < argc; i++)
  193. {
  194. if (strcmp( argv[i], "Single" ) == 0)
  195. thread_mode = COINIT_SINGLETHREADED;
  196. else if (strcmp( argv[i], "Multi" ) == 0)
  197. thread_mode = COINIT_MULTITHREADED;
  198. else if (strcmp( argv[i], "-o" ) == 0)
  199. {
  200. if (argv[++i] == NULL)
  201. {
  202. printf( "You must include an object count after the -o option.\n" );
  203. return FALSE;
  204. }
  205. sscanf( argv[i], "%d", &num_objects );
  206. }
  207. else if (strcmp( argv[i], "-i" ) == 0)
  208. {
  209. if (argv[++i] == NULL)
  210. {
  211. printf( "You must include an object count after the -i option.\n" );
  212. return FALSE;
  213. }
  214. sscanf( argv[i], "%d", &num_iterations );
  215. }
  216. else
  217. {
  218. printf( "You don't know what you are doing!\n" );
  219. }
  220. }
  221. return TRUE;
  222. }
  223. /*************************************************************************/
  224. void MarshalTest()
  225. {
  226. HANDLE file;
  227. HRESULT result;
  228. IMoniker *moniker;
  229. IBindCtx *bindctx;
  230. WCHAR *wide_name;
  231. unsigned char *name;
  232. int i;
  233. IPerf *perf;
  234. // Initialize OLE.
  235. result = OleInitialize(NULL);
  236. if (FAILED(result))
  237. {
  238. printf( "Could not initialize OLE: 0x%x\n", result );
  239. return;
  240. }
  241. // Create file.
  242. file = CreateFile( TEST_FILE, 0, 0, NULL, CREATE_ALWAYS,
  243. FILE_ATTRIBUTE_NORMAL, NULL );
  244. if (file == INVALID_HANDLE_VALUE)
  245. {
  246. printf( "Could not create file." );
  247. return;
  248. }
  249. // Create file moniker.
  250. result = CreateFileMoniker( TEST_FILE, &moniker );
  251. if (FAILED(result))
  252. {
  253. printf( "Could not create file moniker: 0x%x\n", result );
  254. return;
  255. }
  256. // Get a bind context.
  257. result = CreateBindCtx( NULL, &bindctx );
  258. if (FAILED(result))
  259. {
  260. printf( "Could not create bind context: 0x%x\n", result );
  261. return;
  262. }
  263. // Display name.
  264. result = moniker->GetDisplayName( bindctx, NULL, &wide_name );
  265. if (FAILED(result))
  266. {
  267. printf( "Could not get display name: 0x%x\n", result );
  268. return;
  269. }
  270. // Convert the string to ascii and print it.
  271. name = (unsigned char *) wide_name;
  272. i = 0;
  273. while (wide_name[i] != 0)
  274. name[i] = wide_name[i++];
  275. name[i] = 0;
  276. printf( "The moniker is called <%s>\n", name );
  277. // Free string.
  278. CoTaskMemFree( wide_name );
  279. // Get a test object.
  280. result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
  281. (void **) &perf );
  282. if (!SUCCEEDED(result))
  283. {
  284. printf( "Could not create instance of performance server: %x\n", result );
  285. return;
  286. }
  287. // Pass moniker to server.
  288. result = perf->PassMoniker( moniker );
  289. if (FAILED(result))
  290. {
  291. printf( "Could not give moniker to server: 0x%x\n", result );
  292. return;
  293. }
  294. // Release everything.
  295. CloseHandle( file );
  296. moniker->Release();
  297. bindctx->Release();
  298. perf->Release();
  299. OleUninitialize();
  300. }
  301. //+--------------------------------------------------------------
  302. // Function: Main
  303. //
  304. // Synopsis: Executes the BasicBnd test
  305. //
  306. // Effects: None
  307. //
  308. //
  309. // Returns: Exits with exit code 0 if success, 1 otherwise
  310. //
  311. // History: 05-Mar-92 Sarahj Created
  312. //
  313. //---------------------------------------------------------------
  314. int _cdecl main(int argc, char *argv[])
  315. {
  316. BOOL initialized = FALSE;
  317. HRESULT hresult = S_OK;
  318. BOOL fFailed = FALSE;
  319. // Parse the command line arguments.
  320. if (!parse( argc, argv ))
  321. return 0;
  322. // Print the process id.
  323. printf( "Hi, I am %x.\n", GetCurrentProcessId() );
  324. // Time event creation.
  325. // EventTest();
  326. // return 1;
  327. // Pass around monikers.
  328. // MarshalTest();
  329. // Measure message queue APIs.
  330. // QueryMsg();
  331. // Print the thread mode.
  332. if (thread_mode == COINIT_SINGLETHREADED)
  333. {
  334. printf( "Measuring performance for the single threaded mode.\n" );
  335. }
  336. else
  337. {
  338. printf( "Measuring performance for the multithreaded mode.\n" );
  339. }
  340. // must be called before any other OLE API
  341. hresult = OleInitialize(NULL);
  342. if (FAILED(hresult))
  343. {
  344. printf("OleInitialize Failed with %lx\n", hresult);
  345. goto exit_main;
  346. }
  347. initialized = TRUE;
  348. if (fFailed = DoTest())
  349. goto exit_main;
  350. /*
  351. // Uninitialize and rerun in the other thread mode.
  352. OleUninitialize();
  353. if (thread_mode == COINIT_SINGLETHREADED)
  354. thread_mode = COINIT_MULTITHREADED;
  355. else
  356. thread_mode = COINIT_SINGLETHREADED;
  357. // Print the thread mode.
  358. if (thread_mode == COINIT_SINGLETHREADED)
  359. printf( "Measuring performance for the single threaded mode.\n" );
  360. else
  361. printf( "Measuring performance for the multithreaded mode.\n" );
  362. // must be called before any other OLE API
  363. hresult = OleInitialize(NULL);
  364. if (FAILED(hresult))
  365. {
  366. printf("OleInitialize Failed with %lx\n", hresult);
  367. goto exit_main;
  368. }
  369. if (fFailed = DoTest())
  370. goto exit_main;
  371. */
  372. exit_main:
  373. if (initialized)
  374. OleUninitialize();
  375. if (!fFailed)
  376. {
  377. printf("\nCairole: PASSED\n");
  378. }
  379. else
  380. {
  381. printf("\nCairole: FAILED\n");
  382. }
  383. return fFailed;
  384. }
  385. /*************************************************************************/
  386. DWORD _stdcall MsgHelper( void *param )
  387. {
  388. int i;
  389. // Alternately signal and wait on an event. Do it one time too many
  390. // because the main thread calls once to let us get set up.
  391. for (i = 0; i < num_iterations+1; i++)
  392. {
  393. WaitForSingleObject( helper_wait, INFINITE );
  394. SetEvent( main_wait );
  395. }
  396. #define must_return_a_value return 0
  397. must_return_a_value;
  398. }
  399. /*************************************************************************/
  400. void QueryMsg()
  401. {
  402. DWORD time_first;
  403. DWORD waste;
  404. int i;
  405. HANDLE helper;
  406. DWORD thread_id;
  407. // Create an event.
  408. helper_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
  409. if (helper_wait == NULL)
  410. {
  411. printf( "Could not create event.\n" );
  412. return;
  413. }
  414. main_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
  415. if (main_wait == NULL)
  416. {
  417. printf( "Could not create event.\n" );
  418. return;
  419. }
  420. // Measure how long it takes to loop.
  421. waste = GetTickCount();
  422. for (i = 0; i < num_iterations; i++)
  423. ;
  424. waste = GetTickCount() - waste;
  425. // Measure how long it takes to query the message queue.
  426. time_first = GetTickCount();
  427. for (i = 0; i < num_iterations; i++)
  428. GetQueueStatus( QS_ALLINPUT );
  429. time_first = GetTickCount() - time_first - waste;
  430. printf( "%d uS/GetQueueStatus\n", time_first*1000/num_iterations );
  431. // Start a thread to wake up this one.
  432. helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
  433. &thread_id );
  434. if (helper == NULL)
  435. {
  436. printf( "Could not create helper thread.\n" );
  437. return;
  438. }
  439. // Call MsgWaitForMultipleObjects once to let the thread get started.
  440. SetEvent( helper_wait );
  441. MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
  442. INFINITE, QS_ALLINPUT );
  443. // Measure how long it takes to call MsgWaitForMultipleObjects.
  444. time_first = GetTickCount();
  445. for (i = 0; i < num_iterations; i++)
  446. {
  447. SetEvent( helper_wait );
  448. MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
  449. INFINITE, QS_ALLINPUT );
  450. }
  451. time_first = GetTickCount() - time_first - waste;
  452. printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
  453. // Start a thread to wake up this one.
  454. helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
  455. &thread_id );
  456. if (helper == NULL)
  457. {
  458. printf( "Could not create helper thread.\n" );
  459. return;
  460. }
  461. // Let the thread get started.
  462. SetEvent( helper_wait );
  463. WaitForSingleObject( main_wait, INFINITE );
  464. // Measure how long it takes to switch threads just using events.
  465. time_first = GetTickCount();
  466. for (i = 0; i < num_iterations; i++)
  467. {
  468. SetEvent( helper_wait );
  469. WaitForSingleObject( main_wait, INFINITE );
  470. }
  471. time_first = GetTickCount() - time_first - waste;
  472. printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
  473. // Don't bother cleaning up.
  474. }
  475.