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//-----------------------------------------------------------------------------
34const int PERF_ATTR_ON = 0x0001; // Are we even updating any counters?
35const 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//.............................................................................
46struct 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//.............................................................................
83struct 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//.............................................................................
161struct 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
195const 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
203struct Perf_GC_Wow64
204{
205public:
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
230struct Perf_GC
231{
232public:
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 ***
264struct Perf_Loading_Wow64
265{
266// Loading
267public:
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
282struct Perf_Loading
283{
284// Loading
285public:
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
305struct 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
322struct 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
337struct 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
353struct 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
374struct 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>
396struct Perf_Security_Wow64
397{
398// Security
399public:
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
412struct Perf_Security
413{
414// Security
415public:
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>
437struct PerfCounterWow64IPCControlBlock
438{
439public:
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
464struct PerfCounterIPCControlBlock
465{
466public:
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