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 | #ifndef __SAMPLEPROFILER_H__ |
6 | #define __SAMPLEPROFILER_H__ |
7 | |
8 | #ifdef FEATURE_PERFTRACING |
9 | |
10 | #include "common.h" |
11 | #include "eventpipe.h" |
12 | |
13 | enum class SampleProfilerSampleType |
14 | { |
15 | Error = 0, |
16 | External = 1, |
17 | Managed = 2 |
18 | }; |
19 | |
20 | class SampleProfiler |
21 | { |
22 | |
23 | // Declare friends. |
24 | friend class EventPipe; |
25 | friend class SampleProfilerEventInstance; |
26 | |
27 | public: |
28 | |
29 | // Enable profiling. |
30 | static void Enable(); |
31 | |
32 | // Disable profiling. |
33 | static void Disable(); |
34 | |
35 | // Set the sampling rate. |
36 | static void SetSamplingRate(unsigned long nanoseconds); |
37 | |
38 | static unsigned long GetSamplingRate() |
39 | { |
40 | LIMITED_METHOD_CONTRACT; |
41 | |
42 | return s_samplingRateInNs; |
43 | } |
44 | |
45 | private: |
46 | |
47 | // Iterate through all managed threads and walk all stacks. |
48 | static void WalkManagedThreads(); |
49 | |
50 | // Profiling thread proc. Invoked on a new thread when profiling is enabled. |
51 | static DWORD WINAPI ThreadProc(void *args); |
52 | |
53 | // Calls either PAL_nanosleep or ClrSleepEx depending on platform |
54 | // Note: Although we specify the time in ns, that is no indication |
55 | // of the actually accuracy with which we will return from sleep |
56 | // In reality Unix will have a minimum granularity of ~10ms |
57 | // and Windows has a default granularity of ~16ms, but can be |
58 | // adjusted to as low as ~1ms |
59 | // Even this however is not gaurenteed. If the system is under load |
60 | // the sampling thread may be delayed up to hundreds of ms due to |
61 | // scheduling priority. There is no way to prevent this from user threads |
62 | // Additionally we may get lucky and there will be an open CPU to run |
63 | // and under light load the timings will achieve great accuracy! |
64 | static void PlatformSleep(unsigned long nanoseconds); |
65 | |
66 | static bool LoadDependencies(); |
67 | static void UnloadDependencies(); |
68 | |
69 | #ifndef FEATURE_PAL |
70 | static HINSTANCE s_hMultimediaLib; |
71 | static PVOID s_timeBeginPeriodFn; |
72 | static PVOID s_timeEndPeriodFn; |
73 | #endif //FEATURE_PAL |
74 | |
75 | static void SetTimeGranularity(); |
76 | static void ResetTimeGranularity(); |
77 | |
78 | // True when profiling is enabled. |
79 | static Volatile<BOOL> s_profilingEnabled; |
80 | |
81 | // The sampling thread. |
82 | static Thread *s_pSamplingThread; |
83 | |
84 | // The provider and event emitted by the profiler. |
85 | static const WCHAR* s_providerName; |
86 | static EventPipeProvider *s_pEventPipeProvider; |
87 | static EventPipeEvent *s_pThreadTimeEvent; |
88 | |
89 | // Event payloads. |
90 | // External represents a sample in external or native code. |
91 | // Managed represents a sample in managed code. |
92 | static BYTE *s_pPayloadExternal; |
93 | static BYTE *s_pPayloadManaged; |
94 | static const unsigned int c_payloadSize = sizeof(unsigned int); |
95 | |
96 | // Thread shutdown event for synchronization between Disable() and the sampling thread. |
97 | static CLREventStatic s_threadShutdownEvent; |
98 | |
99 | // The sampling rate. |
100 | static unsigned long s_samplingRateInNs; |
101 | |
102 | // Whether or not timeBeginPeriod has been used to set the scheduler period |
103 | static bool s_timePeriodIsSet; |
104 | }; |
105 | |
106 | #endif // FEATURE_PERFTRACING |
107 | |
108 | #endif // __SAMPLEPROFILER_H__ |
109 | |