summaryrefslogtreecommitdiff
path: root/src/vm/sampleprofiler.cpp
diff options
context:
space:
mode:
authorVictor "Nate" Graf <nategraf1@gmail.com>2017-12-20 18:07:52 -0800
committerGitHub <noreply@github.com>2017-12-20 18:07:52 -0800
commit7524d72d4f0f634fe5407280b83c25181dc8c556 (patch)
tree119c7edbbd7b3a0aec47d55334d52d1471e3a3da /src/vm/sampleprofiler.cpp
parent9891c8ba8f84ff646455b4493447295c591665f4 (diff)
downloadcoreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.tar.gz
coreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.tar.bz2
coreclr-7524d72d4f0f634fe5407280b83c25181dc8c556.zip
Enable EventPipe across Unix and Windows (#14772)
* [squashed] most work complete to enable EventPipe on Windows * Eventpipe now builds on Windows * Ensure evevntpipe is intialized on Windows * Resolve the location of python from build.cmd * Ensure eventing files are generated when needed * moving linkage declaration to cmake * create new event from constructor * enable FEATURE_EVENT_TRACE and FEATURE_PERF_TRACE everywhere * [WIP] checkpoint in fixing contarct errors * add another possible python location * Fix double delete bug in EventPipeConfiguration destructor * Fix typo in function name * Revert changes to .gitgnore * bump to netstandard1.6 in preperation for new version of TraceEvent * Revert changes to groovy files * revert changes to perf-prep scripts * add common.h and use nothrow * Fix issue which was causing double delete of configprovider * Add new test utilizing TraceEvent * Remove accidentally added local directory reference * Add comment to explain the addition of misc/tracepointprovider.cpp * Add back sys.exit(0) and refactor * Change conditional to be more direct * Better handle NULL config * Initialize m_deleteDefered * Eliminate obsolete field * Fix spelling error * Fix nits * Make smaple progiler timing functions easier to read * Move projects back to netstandard1.4 * Incomplete improvements to EventPipeTrace test * Add event integrity checks to test * Clean up some left over code * Add EventSource based test * Remove unused PAL tests on Windows * Fix Linux build breaks * Minor changes to CMake files * Remove //HACK for hack that was previously removed * Fix formatting and negate a #ifdef * Add conditional to ensure PERFTRACING is not enabled without EVENT_TRACE * Take lock on EventPipeProvider and EventPipeConfiguration destruction * Load winmm.dll at runtime * Change function name and compile conditions * Move typedef into #ifndef * Use the correct config in setup * Change lifecycle managment of EventPipeConfiguration's configuration provider * Enable EventPipe tests pri0 and disable broken tests * Replace python3 only error with python2 compatable one * Make common.csproj build pri0 * Change TraceEvent version to 2.0.2 to match published verison * Address cross build failure * Remove use of undefined variable * Add crossgen fix to .cmd * Use more specific types to avoid marshalling errors * Use Assert-style statements and remove one check * Fix cross arch build * Fix flipped branch * Bring build.cmd changes to build.sh * Fix cmake writing * Revert "Bring build.cmd changes to build.sh" This reverts commit 893c6492548d8bc9859ebba5b1b810aa630fac63. * remove stdlib.h * Fix out of order null check
Diffstat (limited to 'src/vm/sampleprofiler.cpp')
-rw-r--r--src/vm/sampleprofiler.cpp163
1 files changed, 158 insertions, 5 deletions
diff --git a/src/vm/sampleprofiler.cpp b/src/vm/sampleprofiler.cpp
index d99667eea2..ade21669c4 100644
--- a/src/vm/sampleprofiler.cpp
+++ b/src/vm/sampleprofiler.cpp
@@ -11,6 +11,13 @@
#ifdef FEATURE_PERFTRACING
+#ifndef FEATURE_PAL
+#include <mmsystem.h>
+#endif //FEATURE_PAL
+
+// To avoid counting zeros in conversions
+#define MILLION * 1000000
+
Volatile<BOOL> SampleProfiler::s_profilingEnabled = false;
Thread* SampleProfiler::s_pSamplingThread = NULL;
const WCHAR* SampleProfiler::s_providerName = W("Microsoft-DotNETCore-SampleProfiler");
@@ -19,7 +26,16 @@ EventPipeEvent* SampleProfiler::s_pThreadTimeEvent = NULL;
BYTE* SampleProfiler::s_pPayloadExternal = NULL;
BYTE* SampleProfiler::s_pPayloadManaged = NULL;
CLREventStatic SampleProfiler::s_threadShutdownEvent;
-long SampleProfiler::s_samplingRateInNs = 1000000; // 1ms
+unsigned long SampleProfiler::s_samplingRateInNs = 1 MILLION; // 1ms
+bool SampleProfiler::s_timePeriodIsSet = FALSE;
+
+#ifndef FEATURE_PAL
+PVOID SampleProfiler::s_timeBeginPeriodFn = NULL;
+PVOID SampleProfiler::s_timeEndPeriodFn = NULL;
+HINSTANCE SampleProfiler::s_hMultimediaLib = NULL;
+
+typedef MMRESULT (WINAPI *TimePeriodFnPtr) (UINT uPeriod);
+#endif //FEATURE_PAL
void SampleProfiler::Enable()
{
@@ -33,6 +49,8 @@ void SampleProfiler::Enable()
PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
}
CONTRACTL_END;
+
+ LoadDependencies();
if(s_pEventPipeProvider == NULL)
{
@@ -72,6 +90,10 @@ void SampleProfiler::Enable()
{
_ASSERT(!"Unable to create sample profiler thread.");
}
+
+ s_threadShutdownEvent.CreateManualEvent(FALSE);
+
+ SetTimeGranularity();
}
void SampleProfiler::Disable()
@@ -101,12 +123,32 @@ void SampleProfiler::Disable()
// Wait for the sampling thread to clean itself up.
s_threadShutdownEvent.Wait(0, FALSE /* bAlertable */);
+
+ if(s_timePeriodIsSet)
+ {
+ ResetTimeGranularity();
+ }
+ UnloadDependencies();
}
-void SampleProfiler::SetSamplingRate(long nanoseconds)
+void SampleProfiler::SetSamplingRate(unsigned long nanoseconds)
{
LIMITED_METHOD_CONTRACT;
+
+ // If the time period setting was modified by us,
+ // make sure to change it back before changing our period
+ // and losing track of what we set it to
+ if(s_timePeriodIsSet)
+ {
+ ResetTimeGranularity();
+ }
+
s_samplingRateInNs = nanoseconds;
+
+ if(!s_timePeriodIsSet)
+ {
+ SetTimeGranularity();
+ }
}
DWORD WINAPI SampleProfiler::ThreadProc(void *args)
@@ -132,7 +174,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
if(ThreadSuspend::SysIsSuspendInProgress() || (ThreadSuspend::GetSuspensionThread() != 0))
{
// Skip the current sample.
- PAL_nanosleep(s_samplingRateInNs);
+ PlatformSleep(s_samplingRateInNs);
continue;
}
@@ -146,7 +188,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
ThreadSuspend::RestartEE(FALSE /* bFinishedGC */, TRUE /* SuspendSucceeded */);
// Wait until it's time to sample again.
- PAL_nanosleep(s_samplingRateInNs);
+ PlatformSleep(s_samplingRateInNs);
}
}
@@ -156,7 +198,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
// Signal Disable() that the thread has been destroyed.
s_threadShutdownEvent.Set();
-
+
return S_OK;
}
@@ -201,4 +243,115 @@ void SampleProfiler::WalkManagedThreads()
}
}
+void SampleProfiler::PlatformSleep(unsigned long nanoseconds)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifdef FEATURE_PAL
+ PAL_nanosleep(nanoseconds);
+#else //FEATURE_PAL
+ ClrSleepEx(s_samplingRateInNs / 1 MILLION, FALSE);
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::SetTimeGranularity()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ // Attempt to set the systems minimum timer period to the sampling rate
+ // If the sampling rate is lower than the current system setting (16ms by default),
+ // this will cause the OS to wake more often for scheduling descsion, allowing us to take samples
+ // Note that is effects a system-wide setting and when set low will increase the amount of time
+ // the OS is on-CPU, decreasing overall system performance and increasing power consumption
+ if(s_timeBeginPeriodFn != NULL)
+ {
+ if(((TimePeriodFnPtr) s_timeBeginPeriodFn)(s_samplingRateInNs / 1 MILLION) == TIMERR_NOERROR)
+ {
+ s_timePeriodIsSet = TRUE;
+ }
+ }
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::ResetTimeGranularity()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ // End the modifications we had to the timer period in Enable
+ if(s_timeEndPeriodFn != NULL)
+ {
+ if(((TimePeriodFnPtr) s_timeEndPeriodFn)(s_samplingRateInNs / 1 MILLION) == TIMERR_NOERROR)
+ {
+ s_timePeriodIsSet = FALSE;
+ }
+ }
+#endif //FEATURE_PAL
+}
+
+bool SampleProfiler::LoadDependencies()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ s_hMultimediaLib = WszLoadLibrary(W("winmm.dll"));
+
+ if (s_hMultimediaLib != NULL)
+ {
+ s_timeBeginPeriodFn = (PVOID) GetProcAddress(s_hMultimediaLib, "timeBeginPeriod");
+ s_timeEndPeriodFn = (PVOID) GetProcAddress(s_hMultimediaLib, "timeEndPeriod");
+ }
+
+ return s_hMultimediaLib != NULL && s_timeBeginPeriodFn != NULL && s_timeEndPeriodFn != NULL;
+#else
+ return FALSE;
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::UnloadDependencies()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ if (s_hMultimediaLib != NULL)
+ {
+ FreeLibrary(s_hMultimediaLib);
+ s_hMultimediaLib = NULL;
+ s_timeBeginPeriodFn = NULL;
+ s_timeEndPeriodFn = NULL;
+ }
+#endif //FEATURE_PAL
+}
+
#endif // FEATURE_PERFTRACING