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.

401 lines
9.5 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1994-1999
  3. Module Name:
  4. RtSvr.c
  5. Abstract:
  6. Server side of RPC runtime scale performance test.
  7. Author:
  8. Mario Goertzel (mariogo) 31-Mar-1994
  9. Revision History:
  10. 18/7/96 [MarioGo] - cloned from rpcrt test server.
  11. --*/
  12. #include <rpcperf.h>
  13. #include <rpcrt.h>
  14. // Usage
  15. const char *USAGE =
  16. "[-i iterations] -r [report interval] [-l logfile] [-n clients] [-n minthreads] [-n case]\n"
  17. " Iterations - 4\n"
  18. " Report - 15 seconds\n"
  19. " Clients - default 1\n"
  20. " MinThreads - default 3\n"
  21. " Cases, you may specify one, default is 1:\n"
  22. " 1: Null Call\n"
  23. " 2: Null Call (Non-Idem)\n"
  24. " 3: Buffers Call\n"
  25. " Add [-n in size], [-n out size], defaults of 500 in/out\n"
  26. " 4: Maybe Call\n"
  27. " 5: Bind and Call\n"
  28. "\n"
  29. ;
  30. //
  31. // Globals making it easier.
  32. //
  33. BOOL fClientsGoHome = FALSE;
  34. long Clients, ActiveClients, ClientsLeft;
  35. DWORD TestCase = 1;
  36. DWORD InSize = 500;
  37. DWORD OutSize = 500;
  38. CRITICAL_SECTION CritSec;
  39. HANDLE GoEvent = 0;
  40. #define RPC_PH_KEEP_STATS 100
  41. #define RPC_PH_ACCOUNT_FOR_MAX_CALLS 101
  42. #ifdef STATS
  43. BOOL RPCRTAPI RPC_ENTRY RpcSetPerformanceHint(int PerformanceHint, void *pValue);
  44. #endif
  45. char *TestNames[TEST_MAX] =
  46. {
  47. "Void Call\n",
  48. "Void Call (non-idem)\n",
  49. "Buffer Call %d (in) %d (out)\n",
  50. "Maybe Calls\n",
  51. "Bind calls\n"
  52. };
  53. typedef struct
  54. {
  55. DWORD dwRequestsProcessed;
  56. } CLIENT_STATE;
  57. CLIENT_STATE *ClientState;
  58. #ifdef STATS
  59. // exported by RPCRT4
  60. void I_RpcGetStats(DWORD *pdwStat1, DWORD *pdwStat2, DWORD *pdwStat3, DWORD *pdwStat4);
  61. #endif
  62. void WhackReg(void);
  63. //
  64. // Figure out what we're testing and start listening.
  65. //
  66. int __cdecl
  67. main (int argc, char **argv)
  68. {
  69. unsigned int MinThreads;
  70. unsigned long i, j, status;
  71. RPC_BINDING_VECTOR *pBindingVector;
  72. SYSTEMTIME localTime;
  73. OSVERSIONINFO verInfo;
  74. DWORD StartCalls, FinalCalls, TotalCalls, TotalTicks, MinCalls, MaxCalls;
  75. DWORD dwStat1, dwStat2, dwStat3, dwStat4;
  76. InitAllocator();
  77. ParseArgv(argc, argv);
  78. MinThreads = 3;
  79. ClientsLeft = Clients = 1;
  80. ActiveClients = 0;
  81. // DoTest();
  82. if (Options[0] > 0)
  83. ClientsLeft = Clients = Options[0];
  84. ClientState = MIDL_user_allocate(sizeof(CLIENT_STATE) * Clients);
  85. ZeroMemory(ClientState, sizeof(CLIENT_STATE) * Clients);
  86. if (Options[1] > 0)
  87. MinThreads = Options[1];
  88. if (Options[2] < 0)
  89. {
  90. TestCase = 1;
  91. }
  92. else
  93. {
  94. TestCase = Options[2];
  95. if (TestCase < 1 || TestCase > TEST_MAX)
  96. {
  97. printf("Error: test case %d out of range\n", Options[2]);
  98. TestCase = 1;
  99. }
  100. }
  101. TestCase--;
  102. #ifdef STATS
  103. if (TestCase == 0)
  104. {
  105. BOOL fValue = FALSE;
  106. RpcSetPerformanceHint(RPC_PH_KEEP_STATS, &fValue);
  107. RpcSetPerformanceHint(RPC_PH_ACCOUNT_FOR_MAX_CALLS, &fValue);
  108. }
  109. #endif
  110. if (Iterations == 1000)
  111. {
  112. Iterations = 4;
  113. }
  114. if (Options[3] > 0)
  115. {
  116. InSize = Options[3];
  117. }
  118. if (Options[4] > 0)
  119. {
  120. OutSize = Options[4];
  121. }
  122. // if a log file is on, make the output a bit more log-file friendly
  123. if (LogFileName)
  124. {
  125. GetLocalTime(&localTime);
  126. Dump("\n\n\n**** Perf Test Run ****");
  127. Dump("%d/%d/%d %d:%d:%d\n", localTime.wMonth, localTime.wDay, localTime.wYear,
  128. localTime.wHour, localTime.wMinute, localTime.wSecond);
  129. }
  130. InitializeCriticalSection(&CritSec);
  131. #ifdef _WIN64
  132. // NtCurrentTeb()->ReservedForNtRpc = (PVOID)1;
  133. // WhackReg();
  134. #endif
  135. GoEvent = CreateEvent(0,
  136. TRUE,
  137. FALSE,
  138. 0);
  139. //
  140. // Actually start the server
  141. //
  142. if (Endpoint)
  143. {
  144. status = RpcServerUseProtseqEpA(Protseq, 300, Endpoint, 0);
  145. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  146. }
  147. else
  148. {
  149. char *string_binding;
  150. status = RpcServerUseProtseqA(Protseq, 300, 0);
  151. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  152. status = RpcServerInqBindings(&pBindingVector);
  153. CHECK_STATUS(status, "RpcServerInqBindings");
  154. status = RpcEpRegister(_RpcRuntimeScalePerf_v1_0_s_ifspec,
  155. pBindingVector,
  156. 0,
  157. 0);
  158. CHECK_STATUS(status, "RpcEpRegister");
  159. status = RpcBindingToStringBindingA(pBindingVector->BindingH[0],
  160. &string_binding);
  161. CHECK_STATUS(status, "RpcBindingToStringBinding");
  162. status = RpcStringBindingParseA(string_binding,
  163. 0, 0, 0, &Endpoint, 0);
  164. CHECK_STATUS(status, "RpcStringBindingParse");
  165. printf("Listening to %s:[%s]\n\n", Protseq, Endpoint);
  166. }
  167. status =
  168. RpcServerRegisterIf(_RpcRuntimeScalePerf_v1_0_s_ifspec,0,0);
  169. CHECK_STATUS(status, "RpcServerRegisterIf");
  170. status = RpcServerRegisterAuthInfo(NULL,
  171. RPC_C_AUTHN_WINNT,
  172. NULL,
  173. NULL);
  174. CHECK_STATUS(status, "RpcServerRegisterAuthInfo (NTLM)");
  175. memset(&verInfo, 0, sizeof(verInfo));
  176. verInfo.dwOSVersionInfoSize = sizeof(verInfo);
  177. status = GetVersionEx(&verInfo);
  178. if (status == FALSE)
  179. {
  180. printf("Couldn't get system version (%d) - exitting\n", GetLastError());
  181. exit(2);
  182. }
  183. if ((verInfo.dwMajorVersion >= 5) && (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT))
  184. {
  185. status = RpcServerRegisterAuthInfo(NULL,
  186. RPC_C_AUTHN_GSS_KERBEROS,
  187. NULL,
  188. NULL);
  189. CHECK_STATUS(status, "RpcServerRegisterAuthInfo (KERBEROS)");
  190. status = RpcServerRegisterAuthInfo(NULL,
  191. RPC_C_AUTHN_GSS_NEGOTIATE,
  192. NULL,
  193. NULL);
  194. CHECK_STATUS(status, "RpcServerRegisterAuthInfo (SNEGO)");
  195. }
  196. printf("Clients %d, MinThreads %d\n",
  197. Clients,
  198. MinThreads);
  199. printf("Server listening\n\n");
  200. status = RpcServerListen(MinThreads, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
  201. CHECK_STATUS(status, "RpcServerListen");
  202. printf("Running test: ");
  203. printf(TestNames[TestCase], InSize, OutSize);
  204. WaitForSingleObject(GoEvent, INFINITE);
  205. Sleep(1000);
  206. // Collect and report results. Signal test shutdown when finished.
  207. for (i = 0; i < Iterations; i++)
  208. {
  209. StartTime();
  210. StartCalls = 0;
  211. for (j = 0; j < (ULONG)Clients; j++ )
  212. {
  213. StartCalls += ClientState[j].dwRequestsProcessed;
  214. }
  215. Sleep(Interval * 1000);
  216. FinalCalls = MaxCalls = 0;
  217. MinCalls = ~0;
  218. for (j = 0; j < (ULONG)Clients; j++)
  219. {
  220. DWORD t;
  221. t = ClientState[j].dwRequestsProcessed;
  222. FinalCalls += t;
  223. if (t < MinCalls)
  224. {
  225. MinCalls = t;
  226. }
  227. if (t > MaxCalls)
  228. {
  229. MaxCalls = t;
  230. }
  231. }
  232. TotalCalls = FinalCalls - StartCalls;
  233. TotalTicks = FinishTiming();
  234. Dump("Ticks: %4d, Total: %4d, Average %4d, TPS %3d\n",
  235. TotalTicks,
  236. TotalCalls,
  237. TotalCalls / Clients,
  238. TotalCalls * 1000 / TotalTicks
  239. );
  240. Verbose("Max: %d, Min: %d\n", MaxCalls, MinCalls);
  241. }
  242. fClientsGoHome = TRUE;
  243. Sleep(5000);
  244. #ifdef STATS
  245. I_RpcGetStats(&dwStat1, &dwStat2, &dwStat3, &dwStat4);
  246. printf("Stats are: %ld, %ld, %ld, %ld\n", dwStat1, dwStat2, dwStat3, dwStat4);
  247. #endif
  248. printf("Test Complete\n");
  249. return 0;
  250. }
  251. //
  252. // Control APIs that the client(s) call to sync on test cases, iterations
  253. // and to report results.
  254. //
  255. error_status_t
  256. _BeginTest(handle_t b,
  257. DWORD *ClientId,
  258. DWORD *pTestCase,
  259. DWORD *pInSize,
  260. DWORD *pOutSize )
  261. {
  262. long status = 0;
  263. EnterCriticalSection(&CritSec);
  264. if (ActiveClients < Clients)
  265. {
  266. *ClientId = ActiveClients;
  267. ActiveClients++;
  268. }
  269. else
  270. {
  271. status = PERF_TOO_MANY_CLIENTS;
  272. }
  273. LeaveCriticalSection(&CritSec);
  274. *pTestCase = TestCase;
  275. *pInSize = InSize;
  276. *pOutSize = OutSize;
  277. // Either wait for the rest of the clients or signal the clients to go.
  278. if (status == 0)
  279. {
  280. if (*ClientId < (ULONG)Clients - 1 )
  281. {
  282. // WaitForSingleObject(GoEvent, INFINITE);
  283. }
  284. else
  285. {
  286. SetEvent(GoEvent);
  287. }
  288. }
  289. return status;
  290. }
  291. #define TEST_BODY { ClientState[client].dwRequestsProcessed++; \
  292. if (fClientsGoHome) return PERF_TESTS_DONE; \
  293. return 0; \
  294. }
  295. DWORD _NullCall(handle_t h, DWORD client)
  296. TEST_BODY
  297. void _MaybeCall (handle_t h, DWORD client)
  298. {
  299. ClientState[client].dwRequestsProcessed++;
  300. }
  301. DWORD _NICall (handle_t h, DWORD client)
  302. TEST_BODY
  303. DWORD _BufferCall(handle_t h, DWORD client, long crq, byte inb[], long crp, byte outb[])
  304. TEST_BODY