1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | //----------------------------------------------------------------------------- |
5 | // PerfCounterDefs.h |
6 | // |
7 | // Internal Interface for CLR to use Performance counters |
8 | //----------------------------------------------------------------------------- |
9 | |
10 | |
11 | #ifndef _PerfCounterDefs_h_ |
12 | #define _PerfCounterDefs_h_ |
13 | |
14 | #include "contract.h" |
15 | |
16 | //----------------------------------------------------------------------------- |
17 | // PerfCounters are only enabled if ENABLE_PERF_COUNTERS is defined. |
18 | // If we know we want them (such as in the impl or perfmon, then define this |
19 | // in before we include this header, else define this from the sources file. |
20 | // |
21 | // Note that some platforms don't use perfcounters, so to avoid a build |
22 | // break, you must wrap PerfCounter code (such as instrumenting in either |
23 | // #ifdef or use the COUNTER_ONLY(x) macro (defined below) |
24 | // |
25 | |
26 | //----------------------------------------------------------------------------- |
27 | // Name of global IPC block |
28 | #define SHARED_PERF_IPC_NAME W("SharedPerfIPCBlock") |
29 | |
30 | |
31 | //----------------------------------------------------------------------------- |
32 | // Attributes for the IPC block |
33 | //----------------------------------------------------------------------------- |
34 | const int PERF_ATTR_ON = 0x0001; // Are we even updating any counters? |
35 | const int PERF_ATTR_GLOBAL = 0x0002; // Is this a global or private block? |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | //............................................................................. |
42 | // Tri Counter. Support for the common trio of counters (Total, Current, and |
43 | // Instantaneous). This compiles to the same thing if we had them all separate, |
44 | // but it's a lot cleaner this way. |
45 | //............................................................................. |
46 | struct TRICOUNT |
47 | { |
48 | DWORD Cur; // Current, has +, - |
49 | DWORD Total; // Total, has only + |
50 | inline void operator++(int) { |
51 | LIMITED_METHOD_CONTRACT; |
52 | Cur ++; Total ++; |
53 | } |
54 | inline void operator--(int) { |
55 | LIMITED_METHOD_CONTRACT; |
56 | Cur --; |
57 | } |
58 | inline void operator+=(int delta) { |
59 | LIMITED_METHOD_CONTRACT; |
60 | Cur += delta; Total += delta; |
61 | } |
62 | inline void operator-=(int delta) { |
63 | LIMITED_METHOD_CONTRACT; |
64 | Cur -= delta; |
65 | } |
66 | inline void operator=(int delta) { |
67 | LIMITED_METHOD_CONTRACT; |
68 | Cur = delta; |
69 | Total = delta; |
70 | } |
71 | inline void operator+=(TRICOUNT delta) { |
72 | LIMITED_METHOD_CONTRACT; |
73 | Cur += delta.Cur; Total += delta.Total; |
74 | } |
75 | |
76 | }; |
77 | |
78 | //............................................................................. |
79 | // Interlocked Tri Counter. Support for the common trio of counters (Total, Current, |
80 | // and Instantaneous). This compiles to the same thing if we had them all separate, |
81 | // but it's a lot cleaner this way. |
82 | //............................................................................. |
83 | struct TRICOUNT_IL |
84 | { |
85 | DWORD Cur; // Current, has +, - |
86 | DWORD Total; // Total, has only + |
87 | inline void operator++(int) { |
88 | LIMITED_METHOD_CONTRACT; |
89 | InterlockedIncrement((LPLONG)&Cur); InterlockedIncrement((LPLONG)&Total); |
90 | } |
91 | inline void operator--(int) { |
92 | LIMITED_METHOD_CONTRACT; |
93 | InterlockedDecrement((LPLONG)&Cur); |
94 | } |
95 | inline void operator+=(int delta) { |
96 | LIMITED_METHOD_CONTRACT; |
97 | while (TRUE) |
98 | { |
99 | LONG old_Cur = Cur; |
100 | if (InterlockedCompareExchange((LPLONG)&Cur, Cur+delta, old_Cur) == old_Cur) |
101 | break; |
102 | } |
103 | while (TRUE) |
104 | { |
105 | LONG old_Total = Total; |
106 | if (InterlockedCompareExchange((LPLONG)&Total, Total+delta, old_Total) == old_Total) |
107 | break; |
108 | } |
109 | } |
110 | inline void operator-=(int delta) { |
111 | LIMITED_METHOD_CONTRACT; |
112 | while (TRUE) |
113 | { |
114 | LONG old_Cur = Cur; |
115 | if (InterlockedCompareExchange((LPLONG)&Cur, Cur-delta, old_Cur) == old_Cur) |
116 | break; |
117 | } |
118 | } |
119 | inline void operator=(int delta) { |
120 | LIMITED_METHOD_CONTRACT; |
121 | while (TRUE) |
122 | { |
123 | LONG old_Cur = Cur; |
124 | if (InterlockedCompareExchange((LPLONG)&Cur, delta, old_Cur) == old_Cur) |
125 | break; |
126 | } |
127 | |
128 | while (TRUE) |
129 | { |
130 | LONG old_Total = Total; |
131 | if (InterlockedCompareExchange((LPLONG)&Total, delta, old_Total) == old_Total) |
132 | break; |
133 | } |
134 | } |
135 | inline void operator+=(TRICOUNT_IL delta) { |
136 | LIMITED_METHOD_CONTRACT; |
137 | while (TRUE) |
138 | { |
139 | LONG old_Cur = Cur; |
140 | if (InterlockedCompareExchange((LPLONG)&Cur, Cur+delta.Cur, old_Cur) == old_Cur) |
141 | break; |
142 | } |
143 | while (TRUE) |
144 | { |
145 | LONG old_Total = Total; |
146 | if (InterlockedCompareExchange((LPLONG)&Total, Total+delta.Total, old_Total) == old_Total) |
147 | break; |
148 | } |
149 | } |
150 | |
151 | }; |
152 | |
153 | |
154 | //............................................................................. |
155 | // Dual Counter. Support for the (Total and Instantaneous (rate)). Helpful in cases |
156 | // where the current value is always same as the total value. ie. the counter is never |
157 | // decremented. |
158 | // This compiles to the same thing if we had them separate, but it's a lot cleaner |
159 | // this way. |
160 | //............................................................................. |
161 | struct DUALCOUNT |
162 | { |
163 | DWORD Total; |
164 | inline void operator++(int) { |
165 | LIMITED_METHOD_CONTRACT; |
166 | Total ++; |
167 | } |
168 | |
169 | inline void operator+=(int delta) { |
170 | LIMITED_METHOD_CONTRACT; |
171 | Total += delta; |
172 | } |
173 | |
174 | inline void operator+=(DUALCOUNT delta) { |
175 | LIMITED_METHOD_CONTRACT; |
176 | Total += delta.Total; |
177 | } |
178 | |
179 | |
180 | }; |
181 | |
182 | //----------------------------------------------------------------------------- |
183 | // Format for the Perf Counter IPC Block |
184 | // IPC block is broken up into sections. This marks it easier to marshall |
185 | // into different perfmon objects |
186 | // |
187 | //............................................................................. |
188 | // Naming convention (by prefix): |
189 | // c - Raw count of something. |
190 | // cb- count of bytes |
191 | // time - time value. |
192 | // depth - stack depth |
193 | //----------------------------------------------------------------------------- |
194 | |
195 | const int MAX_TRACKED_GENS = 3; // number of generations we track |
196 | |
197 | // |
198 | // Perf_GC_Wow64 mimics in a 64 bit process, the layout of Perf_GC in a 32 bit process |
199 | // It does this by replacing all size_t by DWORD |
200 | // |
201 | // *** Keep contents of Perf_GC_Wow64 and Perf_GC in sync *** |
202 | |
203 | struct Perf_GC_Wow64 |
204 | { |
205 | public: |
206 | DWORD cGenCollections[MAX_TRACKED_GENS];// count of collects per gen |
207 | DWORD cbPromotedMem[MAX_TRACKED_GENS-1]; // count of promoted memory |
208 | DWORD cbPromotedFinalizationMem; // count of memory promoted due to finalization |
209 | DWORD cProcessID; // process ID |
210 | DWORD cGenHeapSize[MAX_TRACKED_GENS]; // size of heaps per gen |
211 | DWORD cTotalCommittedBytes; // total number of committed bytes. |
212 | DWORD cTotalReservedBytes; // bytes reserved via VirtualAlloc |
213 | DWORD cLrgObjSize; // size of Large Object Heap |
214 | DWORD cSurviveFinalize; // count of instances surviving from finalizing |
215 | DWORD cHandles; // count of GC handles |
216 | DWORD cbAlloc; // bytes allocated |
217 | DWORD cbLargeAlloc; // bytes allocated for Large Objects |
218 | DWORD cInducedGCs; // number of explicit GCs |
219 | DWORD timeInGC; // Time in GC |
220 | DWORD timeInGCBase; // must follow time in GC counter |
221 | |
222 | DWORD cPinnedObj; // # of Pinned Objects |
223 | DWORD cSinkBlocks; // # of sink blocks |
224 | }; |
225 | |
226 | // *** Keep contents of Perf_GC_Wow64 and Perf_GC in sync *** |
227 | #ifndef _WIN64 |
228 | #include <pshpack4.h> |
229 | #endif //#ifndef _WIN64 |
230 | struct Perf_GC |
231 | { |
232 | public: |
233 | size_t cGenCollections[MAX_TRACKED_GENS];// count of collects per gen |
234 | size_t cbPromotedMem[MAX_TRACKED_GENS-1]; // count of promoted memory |
235 | size_t cbPromotedFinalizationMem; // count of memory promoted due to finalization |
236 | size_t cProcessID; // process ID |
237 | size_t cGenHeapSize[MAX_TRACKED_GENS]; // size of heaps per gen |
238 | size_t cTotalCommittedBytes; // total number of committed bytes. |
239 | size_t cTotalReservedBytes; // bytes reserved via VirtualAlloc |
240 | size_t cLrgObjSize; // size of Large Object Heap |
241 | size_t cSurviveFinalize; // count of instances surviving from finalizing |
242 | size_t cHandles; // count of GC handles |
243 | size_t cbAlloc; // bytes allocated |
244 | size_t cbLargeAlloc; // bytes allocated for Large Objects |
245 | size_t cInducedGCs; // number of explicit GCs |
246 | DWORD timeInGC; // Time in GC |
247 | DWORD timeInGCBase; // must follow time in GC counter |
248 | |
249 | size_t cPinnedObj; // # of Pinned Objects |
250 | size_t cSinkBlocks; // # of sink blocks |
251 | |
252 | Perf_GC(); |
253 | Perf_GC(Perf_GC_Wow64& copyFrom); |
254 | }; |
255 | #ifndef _WIN64 |
256 | #include <poppack.h> |
257 | #endif //#ifndef _WIN64 |
258 | |
259 | // |
260 | // Perf_Loading_Wow64 mimics in a 64 bit process, the layout of Perf_Loading |
261 | // in a 32 bit process. It does this by replacing all size_t by DWORD |
262 | // |
263 | // *** Keep contents of Perf_Loading_Wow64 and Perf_Loading in sync *** |
264 | struct Perf_Loading_Wow64 |
265 | { |
266 | // Loading |
267 | public: |
268 | TRICOUNT cClassesLoaded; |
269 | TRICOUNT_IL cAppDomains; // Current # of AppDomains |
270 | TRICOUNT cAssemblies; // Current # of Assemblies. |
271 | UNALIGNED LONGLONG timeLoading; // % time loading |
272 | DWORD cAsmSearchLen; // Avg search length for assemblies |
273 | DUALCOUNT cLoadFailures; // Classes Failed to load |
274 | DWORD cbLoaderHeapSize; // Total size of heap used by the loader |
275 | DUALCOUNT cAppDomainsUnloaded; // Rate at which app domains are unloaded |
276 | }; |
277 | |
278 | // *** Keep contents of Perf_Loading_Wow64 and Perf_Loading in sync *** |
279 | #ifndef _WIN64 |
280 | #include <pshpack4.h> |
281 | #endif //#ifndef _WIN64 |
282 | struct Perf_Loading |
283 | { |
284 | // Loading |
285 | public: |
286 | TRICOUNT cClassesLoaded; |
287 | TRICOUNT_IL cAppDomains; // Current # of AppDomains |
288 | TRICOUNT cAssemblies; // Current # of Assemblies. |
289 | UNALIGNED LONGLONG timeLoading; // % time loading |
290 | DWORD cAsmSearchLen; // Avg search length for assemblies |
291 | DUALCOUNT cLoadFailures; // Classes Failed to load |
292 | size_t cbLoaderHeapSize; // Total size of heap used by the loader |
293 | DUALCOUNT cAppDomainsUnloaded; // Rate at which app domains are unloaded |
294 | |
295 | Perf_Loading(); |
296 | Perf_Loading(Perf_Loading_Wow64& copyFrom); |
297 | }; |
298 | #ifndef _WIN64 |
299 | #include <poppack.h> |
300 | #endif //#ifndef _WIN64 |
301 | |
302 | #ifndef _WIN64 |
303 | #include <pshpack4.h> |
304 | #endif //#ifndef _WIN64 |
305 | struct Perf_Jit |
306 | { |
307 | // Jitting |
308 | DWORD cMethodsJitted; // number of methods jitted |
309 | TRICOUNT cbILJitted; // IL jitted stats |
310 | // DUALCOUNT cbPitched; // Total bytes pitched |
311 | DWORD cJitFailures; // # of standard Jit failures |
312 | DWORD timeInJit; // Time in JIT since last sample |
313 | DWORD timeInJitBase; // Time in JIT base counter |
314 | }; |
315 | #ifndef _WIN64 |
316 | #include <poppack.h> |
317 | #endif //#ifndef _WIN64 |
318 | |
319 | #ifndef _WIN64 |
320 | #include <pshpack4.h> |
321 | #endif //#ifndef _WIN64 |
322 | struct Perf_Excep |
323 | { |
324 | // Exceptions |
325 | DUALCOUNT cThrown; // Number of Exceptions thrown |
326 | DWORD cFiltersExecuted; // Number of Filters executed |
327 | DWORD cFinallysExecuted; // Number of Finallys executed |
328 | DWORD cThrowToCatchStackDepth; // Delta from throw to catch site on stack |
329 | }; |
330 | #ifndef _WIN64 |
331 | #include <poppack.h> |
332 | #endif //#ifndef _WIN64 |
333 | |
334 | #ifndef _WIN64 |
335 | #include <pshpack4.h> |
336 | #endif //#ifndef _WIN64 |
337 | struct Perf_Interop |
338 | { |
339 | // Interop |
340 | DWORD cCCW; // Number of CCWs |
341 | DWORD cStubs; // Number of stubs |
342 | DWORD cMarshalling; // # of time marshalling args and return values. |
343 | DWORD cTLBImports; // Number of tlbs we import |
344 | DWORD cTLBExports; // Number of tlbs we export |
345 | }; |
346 | #ifndef _WIN64 |
347 | #include <poppack.h> |
348 | #endif //#ifndef _WIN64 |
349 | |
350 | #ifndef _WIN64 |
351 | #include <pshpack4.h> |
352 | #endif //#ifndef _WIN64 |
353 | struct Perf_LocksAndThreads |
354 | { |
355 | // Locks |
356 | DUALCOUNT cContention; // # of times in AwareLock::EnterEpilogue() |
357 | TRICOUNT cQueueLength; // Lenght of queue |
358 | // Threads |
359 | DWORD cCurrentThreadsLogical; // Number (created - destroyed) of logical threads |
360 | DWORD cCurrentThreadsPhysical; // Number (created - destroyed) of OS threads |
361 | TRICOUNT cRecognizedThreads; // # of Threads execute in runtime's control |
362 | }; |
363 | #ifndef _WIN64 |
364 | #include <poppack.h> |
365 | #endif //#ifndef _WIN64 |
366 | |
367 | |
368 | // IMPORTANT!!!!!!!: The first two fields in the struct have to be together |
369 | // and be the first two fields in the struct. The managed code in ChannelServices.cs |
370 | // depends on this. |
371 | #ifndef _WIN64 |
372 | #include <pshpack4.h> |
373 | #endif //#ifndef _WIN64 |
374 | struct Perf_Contexts |
375 | { |
376 | // Contexts & Remoting |
377 | DUALCOUNT cRemoteCalls; // # of remote calls |
378 | DWORD cChannels; // Number of current channels |
379 | DWORD cProxies; // Number of context proxies. |
380 | DWORD cClasses; // # of Context-bound classes |
381 | DWORD cObjAlloc; // # of context bound objects allocated |
382 | DWORD cContexts; // The current number of contexts. |
383 | }; |
384 | #ifndef _WIN64 |
385 | #include <poppack.h> |
386 | #endif //#ifndef _WIN64 |
387 | |
388 | // |
389 | // Perf_Security_Wow64 mimics in a 64 bit process, the layout of Perf_Security |
390 | // in a 32 bit process. It does this by packing all members on 4 byte boundary |
391 | // ("timeAuthorize" field which is 8 bytes in size, will get 8 byte aligned |
392 | // on 64 bit by default) |
393 | // |
394 | // *** Keep contents of Perf_Security_Wow64 and Perf_Security in sync *** |
395 | #include <pshpack4.h> |
396 | struct Perf_Security_Wow64 |
397 | { |
398 | // Security |
399 | public: |
400 | DWORD cTotalRTChecks; // Total runtime checks |
401 | UNALIGNED LONGLONG timeAuthorize; // % time authenticating |
402 | DWORD cLinkChecks; // link time checks |
403 | DWORD timeRTchecks; // % time in Runtime checks |
404 | DWORD timeRTchecksBase; // % time in Runtime checks base counter |
405 | DWORD stackWalkDepth; // depth of stack for security checks |
406 | }; |
407 | #include <poppack.h> |
408 | |
409 | #ifndef _WIN64 |
410 | #include <pshpack4.h> |
411 | #endif //#ifndef _WIN64 |
412 | struct Perf_Security |
413 | { |
414 | // Security |
415 | public: |
416 | DWORD cTotalRTChecks; // Total runtime checks |
417 | UNALIGNED LONGLONG timeAuthorize; // % time authenticating |
418 | DWORD cLinkChecks; // link time checks |
419 | DWORD timeRTchecks; // % time in Runtime checks |
420 | DWORD timeRTchecksBase; // % time in Runtime checks base counter |
421 | DWORD stackWalkDepth; // depth of stack for security checks |
422 | |
423 | Perf_Security(); |
424 | Perf_Security(Perf_Security_Wow64& copyFrom); |
425 | }; |
426 | #ifndef _WIN64 |
427 | #include <poppack.h> |
428 | #endif //#ifndef _WIN64 |
429 | |
430 | |
431 | // |
432 | // PerfCounterWow64IPCControlBlock mimics in a 64 bit process, the layout of |
433 | // PerfCounterIPCControlBlock in a 32 bit process. |
434 | // |
435 | // *** Keep contents of PerfCounterWow64IPCControlBlock and PerfCounterIPCControlBlock in sync *** |
436 | #include <pshpack4.h> |
437 | struct PerfCounterWow64IPCControlBlock |
438 | { |
439 | public: |
440 | // Versioning info |
441 | WORD m_cBytes; // size of this entire block |
442 | WORD m_wAttrs; // attributes for this block |
443 | |
444 | // Counter Sections |
445 | Perf_GC_Wow64 m_GC; |
446 | Perf_Contexts m_Context; |
447 | Perf_Interop m_Interop; |
448 | Perf_Loading_Wow64 m_Loading; |
449 | Perf_Excep m_Excep; |
450 | Perf_LocksAndThreads m_LocksAndThreads; |
451 | Perf_Jit m_Jit; |
452 | Perf_Security_Wow64 m_Security; |
453 | }; |
454 | #include <poppack.h> |
455 | |
456 | // Note: PerfMonDll marshalls data out of here by copying a continous block of memory. |
457 | // We can still add new members to the subsections above, but if we change their |
458 | // placement in the structure below, we may break PerfMon's marshalling |
459 | |
460 | // *** Keep contents of PerfCounterWow64IPCControlBlock and PerfCounterIPCControlBlock in sync *** |
461 | #ifndef _WIN64 |
462 | #include <pshpack4.h> |
463 | #endif //#ifndef _WIN64 |
464 | struct PerfCounterIPCControlBlock |
465 | { |
466 | public: |
467 | // Versioning info |
468 | WORD m_cBytes; // size of this entire block |
469 | WORD m_wAttrs; // attributes for this block |
470 | |
471 | // Counter Sections |
472 | Perf_GC m_GC; |
473 | Perf_Contexts m_Context; |
474 | Perf_Interop m_Interop; |
475 | Perf_Loading m_Loading; |
476 | Perf_Excep m_Excep; |
477 | Perf_LocksAndThreads m_LocksAndThreads; |
478 | Perf_Jit m_Jit; |
479 | Perf_Security m_Security; |
480 | |
481 | PerfCounterIPCControlBlock(); |
482 | PerfCounterIPCControlBlock(PerfCounterWow64IPCControlBlock& copyFrom); |
483 | }; |
484 | |
485 | #ifndef _WIN64 |
486 | #include <poppack.h> |
487 | #endif //#ifndef _WIN64 |
488 | |
489 | // |
490 | // Inline definitions |
491 | // |
492 | |
493 | #include "perfcounterdefs.inl" |
494 | |
495 | #endif // _PerfCounterDefs_h_ |
496 | |