diff options
author | Victor "Nate" Graf <nategraf1@gmail.com> | 2017-12-20 18:07:52 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-20 18:07:52 -0800 |
commit | 7524d72d4f0f634fe5407280b83c25181dc8c556 (patch) | |
tree | 119c7edbbd7b3a0aec47d55334d52d1471e3a3da /src/vm/sampleprofiler.cpp | |
parent | 9891c8ba8f84ff646455b4493447295c591665f4 (diff) | |
download | coreclr-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.cpp | 163 |
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 |