private string m_outputFile;
private uint m_circularBufferSizeInMB;
private List<EventPipeProviderConfiguration> m_providers;
+ private TimeSpan m_minTimeBetweenSamples = TimeSpan.FromMilliseconds(1);
internal EventPipeConfiguration(
string outputFile,
get { return m_providers.ToArray(); }
}
+ internal long ProfilerSamplingRateInNanoseconds
+ {
+ // 100 nanoseconds == 1 tick.
+ get { return m_minTimeBetweenSamples.Ticks * 100; }
+ }
+
internal void EnableProvider(string providerName, UInt64 keywords, uint loggingLevel)
{
m_providers.Add(new EventPipeProviderConfiguration(
keywords,
loggingLevel));
}
+
+ internal void SetProfilerSamplingRate(TimeSpan minTimeBetweenSamples)
+ {
+ if(minTimeBetweenSamples.Ticks <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(minTimeBetweenSamples));
+ }
+
+ m_minTimeBetweenSamples = minTimeBetweenSamples;
+ }
}
internal static class EventPipe
EventPipeInternal.Enable(
configuration.OutputFile,
configuration.CircularBufferSizeInMB,
+ configuration.ProfilerSamplingRateInNanoseconds,
providers,
providers.Length);
}
//
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- internal static extern void Enable(string outputFile, uint circularBufferSizeInMB, EventPipeProviderConfiguration[] providers, int numProviders);
+ internal static extern void Enable(string outputFile, uint circularBufferSizeInMB, long profilerSamplingRateInNanoseconds, EventPipeProviderConfiguration[] providers, int numProviders);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
void QCALLTYPE EventPipeInternal::Enable(
__in_z LPCWSTR outputFile,
unsigned int circularBufferSizeInMB,
+ long profilerSamplingRateInNanoseconds,
EventPipeProviderConfiguration *pProviders,
int numProviders)
{
QCALL_CONTRACT;
BEGIN_QCALL;
+ SampleProfiler::SetSamplingRate(profilerSamplingRateInNanoseconds);
EventPipe::Enable(outputFile, circularBufferSizeInMB, pProviders, numProviders);
END_QCALL;
}
static void QCALLTYPE Enable(
__in_z LPCWSTR outputFile,
unsigned int circularBufferSizeInMB,
+ long profilerSamplingRateInNanoseconds,
EventPipeProviderConfiguration *pProviders,
int numProviders);
EventPipeProvider* SampleProfiler::s_pEventPipeProvider = NULL;
EventPipeEvent* SampleProfiler::s_pThreadTimeEvent = NULL;
CLREventStatic SampleProfiler::s_threadShutdownEvent;
-#ifdef FEATURE_PAL
long SampleProfiler::s_samplingRateInNs = 1000000; // 1ms
-#endif
void SampleProfiler::Enable()
{
s_threadShutdownEvent.Wait(0, FALSE /* bAlertable */);
}
+void SampleProfiler::SetSamplingRate(long nanoseconds)
+{
+ LIMITED_METHOD_CONTRACT;
+ s_samplingRateInNs = nanoseconds;
+}
+
DWORD WINAPI SampleProfiler::ThreadProc(void *args)
{
CONTRACTL
if(ThreadSuspend::SysIsSuspendInProgress() || (ThreadSuspend::GetSuspensionThread() != 0))
{
// Skip the current sample.
-#ifdef FEATURE_PAL
PAL_nanosleep(s_samplingRateInNs);
-#else
- ClrSleepEx(1, FALSE);
-#endif
continue;
}
ThreadSuspend::RestartEE(FALSE /* bFinishedGC */, TRUE /* SuspendSucceeded */);
// Wait until it's time to sample again.
-#ifdef FEATURE_PAL
PAL_nanosleep(s_samplingRateInNs);
-#else
- ClrSleepEx(1, FALSE);
-#endif
}
}
// Disable profiling.
static void Disable();
+ // Set the sampling rate.
+ static void SetSamplingRate(long nanoseconds);
+
private:
// Iterate through all managed threads and walk all stacks.
// Thread shutdown event for synchronization between Disable() and the sampling thread.
static CLREventStatic s_threadShutdownEvent;
-#ifdef FEATURE_PAL
// The sampling rate.
static long s_samplingRateInNs;
-#endif
};
#endif // FEATURE_PERFTRACING