mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 16:11:02 +08:00
(profiler_core) Added possibility to control event tracing priority level and to enable/disable event tracing at all.
This commit is contained in:
parent
d8296ad43a
commit
4a40872183
@ -32,32 +32,7 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
||||
\defgroup profiler EasyProfiler
|
||||
*/
|
||||
|
||||
/** If != 0 then EasyProfiler will measure time for blocks storage expansion.
|
||||
If 0 then EasyProfiler will be compiled without blocks of code responsible
|
||||
for measuring these events.
|
||||
|
||||
These are "EasyProfiler.ExpandStorage" blocks on a diagram.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_MEASURE_STORAGE_EXPAND 0
|
||||
|
||||
/** If true then "EasyProfiler.ExpandStorage" events are enabled by default and will be
|
||||
writed to output file or translated over the net.
|
||||
If false then you need to enable these events via GUI if you'll want to see them.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_STORAGE_EXPAND_ENABLED true
|
||||
|
||||
/** If true then EasyProfiler event tracing is enabled by default
|
||||
and will be turned on and off when you call profiler::setEnabled().
|
||||
Otherwise, it have to be turned on via GUI and then it will be
|
||||
turned on/off with next calls of profiler::setEnabled().
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_EVENT_TRACING_ENABLED true
|
||||
// EasyProfiler core API:
|
||||
|
||||
/** Macro for beginning of a block with custom name and color.
|
||||
|
||||
@ -194,6 +169,35 @@ This is just for user's comfort. There is no difference for EasyProfiler GUI bet
|
||||
*/
|
||||
# define EASY_MAIN_THREAD EASY_THREAD("Main")
|
||||
|
||||
/** Enable or disable event tracing (context switch events).
|
||||
|
||||
\note Default value is controlled by EASY_EVENT_TRACING_ENABLED macro.
|
||||
|
||||
\note Change will take effect on the next call to EASY_PROFILER_ENABLE.
|
||||
|
||||
\sa EASY_PROFILER_ENABLE, EASY_EVENT_TRACING_ENABLED
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_SET_EVENT_TRACING_ENABLED(isEnabled) ::profiler::setEventTracingEnabled(isEnabled);
|
||||
|
||||
/** Set event tracing thread priority (low or normal).
|
||||
|
||||
Event tracing with low priority will affect your application performance much more less, but
|
||||
it can be late to gather information about thread/process (thread could be finished to the moment
|
||||
when event tracing thread will be awaken) and you will not see process name and process id
|
||||
information in GUI for such threads. You will still be able to see all context switch events.
|
||||
|
||||
Event tracing with normal priority could gather more information about processes but potentially
|
||||
it could affect performance as it has more work to do. Usually you will not notice any performance
|
||||
breakdown, but if you care about that then you change set event tracing priority level to low.
|
||||
|
||||
\sa EASY_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority) ::profiler::setLowPriorityEventTracing(isLowPriority);
|
||||
|
||||
# ifndef _WIN32
|
||||
/** Macro for setting temporary log-file path for Unix event tracing system.
|
||||
|
||||
@ -210,10 +214,52 @@ This is just for user's comfort. There is no difference for EasyProfiler GUI bet
|
||||
# define EASY_EVENT_TRACING_LOG ::profiler::getContextSwitchLogFilename();
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
|
||||
// EasyProfiler settings:
|
||||
|
||||
/** If != 0 then EasyProfiler will measure time for blocks storage expansion.
|
||||
If 0 then EasyProfiler will be compiled without blocks of code responsible
|
||||
for measuring these events.
|
||||
|
||||
These are "EasyProfiler.ExpandStorage" blocks on a diagram.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_MEASURE_STORAGE_EXPAND 0
|
||||
# define EASY_STORAGE_EXPAND_ENABLED false
|
||||
# define EASY_EVENT_TRACING_ENABLED false
|
||||
|
||||
/** If true then "EasyProfiler.ExpandStorage" events are enabled by default and will be
|
||||
writed to output file or translated over the net.
|
||||
If false then you need to enable these events via GUI if you'll want to see them.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_STORAGE_EXPAND_ENABLED true
|
||||
|
||||
/** If true then EasyProfiler event tracing is enabled by default
|
||||
and will be turned on and off when you call profiler::setEnabled().
|
||||
Otherwise, it have to be turned on via GUI and then it will be
|
||||
turned on/off with next calls of profiler::setEnabled().
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_EVENT_TRACING_ENABLED true
|
||||
|
||||
/** If true then EasyProfiler.ETW thread (Event tracing for Windows) will have low priority by default.
|
||||
|
||||
\sa EASY_SET_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\note You can always change priority level via GUI or API while profiling session is not launched.
|
||||
You don't need to rebuild or restart your application for that.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_LOW_PRIORITY_EVENT_TRACING true
|
||||
|
||||
|
||||
|
||||
#else // #ifndef FULL_DISABLE_PROFILER
|
||||
|
||||
# define EASY_BLOCK(...)
|
||||
# define EASY_FUNCTION(...)
|
||||
# define EASY_END_BLOCK
|
||||
@ -222,13 +268,20 @@ This is just for user's comfort. There is no difference for EasyProfiler GUI bet
|
||||
# define EASY_EVENT(...)
|
||||
# define EASY_THREAD(...)
|
||||
# define EASY_MAIN_THREAD
|
||||
# define EASY_SET_EVENT_TRACING_ENABLED(isEnabled)
|
||||
# define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority)
|
||||
|
||||
# ifndef _WIN32
|
||||
# define EASY_EVENT_TRACING_SET_LOG(filename)
|
||||
# define EASY_EVENT_TRACING_LOG ""
|
||||
# endif
|
||||
|
||||
#endif
|
||||
# define EASY_MEASURE_STORAGE_EXPAND 0
|
||||
# define EASY_STORAGE_EXPAND_ENABLED false
|
||||
# define EASY_EVENT_TRACING_ENABLED false
|
||||
# define EASY_LOW_PRIORITY_EVENT_TRACING true
|
||||
|
||||
#endif // #ifndef FULL_DISABLE_PROFILER
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -455,6 +508,26 @@ namespace profiler {
|
||||
*/
|
||||
PROFILER_API const char* registerThread(const char* _name);
|
||||
|
||||
/** Enable or disable event tracing.
|
||||
|
||||
\note This change will take an effect on the next call of setEnabled(true);
|
||||
|
||||
\sa setEnabled, EASY_SET_EVENT_TRACING_ENABLED
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setEventTracingEnabled(bool _isEnable);
|
||||
|
||||
/** Set event tracing thread priority (low or normal).
|
||||
|
||||
\note This change will take effect on the next call of setEnabled(true);
|
||||
|
||||
\sa setEnabled, EASY_SET_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority);
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Set temporary log-file path for Unix event tracing system.
|
||||
|
||||
|
@ -71,7 +71,7 @@ namespace profiler {
|
||||
auto _contextSwitchEvent = reinterpret_cast<CSwitch*>(_traceEvent->UserData);
|
||||
const auto time = static_cast<::profiler::timestamp_t>(_traceEvent->EventHeader.TimeStamp.QuadPart);
|
||||
|
||||
ProcessInfo* pinfo = nullptr;
|
||||
const char* process_name = "";
|
||||
auto it = THREAD_PROCESS_INFO_TABLE.find(_contextSwitchEvent->NewThreadId);
|
||||
if (it == THREAD_PROCESS_INFO_TABLE.end())
|
||||
{
|
||||
@ -79,10 +79,18 @@ namespace profiler {
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
auto pid = GetProcessIdOfThread(hThread);
|
||||
pinfo = &PROCESS_INFO_TABLE[pid];
|
||||
auto pinfo = &PROCESS_INFO_TABLE[pid];
|
||||
|
||||
if (pinfo->valid == 0)
|
||||
{
|
||||
if (pinfo->name.empty())
|
||||
{
|
||||
static char numbuf[128] = {};
|
||||
sprintf(numbuf, "%u", pid);
|
||||
pinfo->name = numbuf;
|
||||
pinfo->id = pid;
|
||||
}
|
||||
|
||||
// According to documentation, using GetModuleBaseName() requires
|
||||
// PROCESS_QUERY_INFORMATION | PROCESS_VM_READ access rights.
|
||||
// But it works fine with PROCESS_QUERY_LIMITED_INFORMATION instead of PROCESS_QUERY_INFORMATION.
|
||||
@ -94,54 +102,43 @@ namespace profiler {
|
||||
static TCHAR buf[MAX_PATH] = {}; // Using static is safe because processTraceEvent() is called from one thread
|
||||
auto success = GetModuleBaseName(hProc, 0, buf, MAX_PATH);
|
||||
|
||||
if (pinfo->name.empty())
|
||||
{
|
||||
static char numbuf[128] = {};
|
||||
sprintf(numbuf, "%u ", pid);
|
||||
pinfo->name = numbuf;
|
||||
pinfo->id = pid;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
pinfo->name += buf;
|
||||
auto len = strlen(buf);
|
||||
pinfo->name.reserve(pinfo->name.size() + 2 + len);
|
||||
pinfo->name.append(" ", 1);
|
||||
pinfo->name.append(buf, len);
|
||||
pinfo->valid = 1;
|
||||
//printf("PROCESS %u is %s\n", pid, buf);
|
||||
}
|
||||
|
||||
CloseHandle(hProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Can not OpenProcess(%u);\n", pid);
|
||||
pinfo->valid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pinfo->valid > 0)
|
||||
{
|
||||
THREAD_PROCESS_INFO_TABLE[_contextSwitchEvent->NewThreadId] = pinfo;
|
||||
}
|
||||
else if (pinfo->valid < 0)
|
||||
{
|
||||
pinfo = nullptr;
|
||||
THREAD_PROCESS_INFO_TABLE[_contextSwitchEvent->NewThreadId] = nullptr;
|
||||
}
|
||||
process_name = pinfo->name.c_str();
|
||||
THREAD_PROCESS_INFO_TABLE[_contextSwitchEvent->NewThreadId] = pinfo;
|
||||
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Can not OpenThread(%u);\n", _contextSwitchEvent->NewThreadId);
|
||||
THREAD_PROCESS_INFO_TABLE[_contextSwitchEvent->NewThreadId] = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pinfo = it->second;
|
||||
if (pinfo != nullptr && pinfo->valid < 0)
|
||||
pinfo = nullptr;
|
||||
auto pinfo = it->second;
|
||||
if (pinfo != nullptr)
|
||||
process_name = pinfo->name.c_str();
|
||||
}
|
||||
|
||||
MANAGER.beginContextSwitch(_contextSwitchEvent->OldThreadId, time, _contextSwitchEvent->NewThreadId, pinfo ? pinfo->name.c_str() : "");
|
||||
MANAGER.beginContextSwitch(_contextSwitchEvent->OldThreadId, time, _contextSwitchEvent->NewThreadId, process_name);
|
||||
MANAGER.endContextSwitch(_contextSwitchEvent->NewThreadId, time);
|
||||
}
|
||||
|
||||
@ -155,6 +152,7 @@ namespace profiler {
|
||||
|
||||
EasyEventTracer::EasyEventTracer()
|
||||
{
|
||||
m_lowPriority = ATOMIC_VAR_INIT(EASY_LOW_PRIORITY_EVENT_TRACING);
|
||||
}
|
||||
|
||||
EasyEventTracer::~EasyEventTracer()
|
||||
@ -162,6 +160,11 @@ namespace profiler {
|
||||
disable();
|
||||
}
|
||||
|
||||
void EasyEventTracer::setLowPriority(bool _value)
|
||||
{
|
||||
m_lowPriority.store(_value, ::std::memory_order_release);
|
||||
}
|
||||
|
||||
::profiler::EventTracingEnableStatus EasyEventTracer::startTrace(bool _force, int _step)
|
||||
{
|
||||
auto startTraceResult = StartTrace(&m_sessionHandle, KERNEL_LOGGER_NAME, props());
|
||||
@ -242,7 +245,8 @@ namespace profiler {
|
||||
}));
|
||||
|
||||
// Set low priority for event tracing thread
|
||||
SetThreadPriority(m_processThread.native_handle(), THREAD_PRIORITY_LOWEST);
|
||||
if (m_lowPriority.load(::std::memory_order_acquire))
|
||||
SetThreadPriority(m_processThread.native_handle(), THREAD_PRIORITY_LOWEST);
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <evntrace.h>
|
||||
#include <evntcons.h>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include "event_trace_status.h"
|
||||
#include "spin_lock.h"
|
||||
|
||||
@ -30,13 +31,14 @@ namespace profiler {
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
::std::thread m_processThread;
|
||||
Properties m_properties;
|
||||
EVENT_TRACE_LOGFILE m_trace;
|
||||
profiler::spin_lock m_spin;
|
||||
TRACEHANDLE m_sessionHandle = INVALID_PROCESSTRACE_HANDLE;
|
||||
TRACEHANDLE m_openedHandle = INVALID_PROCESSTRACE_HANDLE;
|
||||
bool m_bEnabled = false;
|
||||
::std::thread m_processThread;
|
||||
Properties m_properties;
|
||||
EVENT_TRACE_LOGFILE m_trace;
|
||||
profiler::spin_lock m_spin;
|
||||
::std::atomic_bool m_lowPriority;
|
||||
TRACEHANDLE m_sessionHandle = INVALID_PROCESSTRACE_HANDLE;
|
||||
TRACEHANDLE m_openedHandle = INVALID_PROCESSTRACE_HANDLE;
|
||||
bool m_bEnabled = false;
|
||||
|
||||
public:
|
||||
|
||||
@ -45,6 +47,7 @@ namespace profiler {
|
||||
|
||||
::profiler::EventTracingEnableStatus enable(bool _force = false);
|
||||
void disable();
|
||||
void setLowPriority(bool _value);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -82,6 +82,20 @@ extern "C" {
|
||||
return MANAGER.registerThread(name);// , filename, _funcname, line);
|
||||
}
|
||||
|
||||
PROFILER_API void setEventTracingEnabled(bool _isEnable)
|
||||
{
|
||||
MANAGER.setEventTracingEnabled(_isEnable);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority)
|
||||
{
|
||||
EasyEventTracer::instance().setLowPriority(_isLowPriority);
|
||||
}
|
||||
#else
|
||||
PROFILER_API void setLowPriorityEventTracing(bool) { }
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
PROFILER_API void setContextSwitchLogFilename(const char* name)
|
||||
{
|
||||
@ -245,7 +259,7 @@ ThreadStorage* ProfileManager::_findThreadStorage(profiler::thread_id_t _thread_
|
||||
|
||||
void ProfileManager::storeBlock(const profiler::BaseBlockDescriptor& _desc, const char* _runtimeName)
|
||||
{
|
||||
if (!m_isEnabled || !_desc.enabled())
|
||||
if (!m_isEnabled.load(std::memory_order_acquire) || !_desc.enabled())
|
||||
return;
|
||||
|
||||
profiler::Block b(_desc, _runtimeName);
|
||||
@ -259,7 +273,7 @@ void ProfileManager::storeBlock(const profiler::BaseBlockDescriptor& _desc, cons
|
||||
|
||||
void ProfileManager::beginBlock(Block& _block)
|
||||
{
|
||||
if (!m_isEnabled)
|
||||
if (!m_isEnabled.load(std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
if (THREAD_STORAGE == nullptr)
|
||||
@ -290,7 +304,7 @@ void ProfileManager::storeContextSwitch(profiler::thread_id_t _thread_id, profil
|
||||
|
||||
void ProfileManager::endBlock()
|
||||
{
|
||||
if (!m_isEnabled)
|
||||
if (!m_isEnabled.load(std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
if (THREAD_STORAGE->blocks.openedList.empty())
|
||||
@ -322,11 +336,11 @@ void ProfileManager::endContextSwitch(profiler::thread_id_t _thread_id, profiler
|
||||
|
||||
void ProfileManager::setEnabled(bool isEnable)
|
||||
{
|
||||
m_isEnabled = isEnable;
|
||||
m_isEnabled.store(isEnable, std::memory_order_release);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (isEnable) {
|
||||
if (m_isEventTracingEnabled)
|
||||
if (m_isEventTracingEnabled.load(std::memory_order_acquire))
|
||||
EasyEventTracer::instance().enable(true);
|
||||
} else {
|
||||
EasyEventTracer::instance().disable();
|
||||
@ -334,12 +348,17 @@ void ProfileManager::setEnabled(bool isEnable)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ProfileManager::setEventTracingEnabled(bool _isEnable)
|
||||
{
|
||||
m_isEventTracingEnabled.store(_isEnable, std::memory_order_release);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
{
|
||||
const bool wasEnabled = m_isEnabled;
|
||||
const bool eventTracingEnabled = m_isEventTracingEnabled;
|
||||
const bool wasEnabled = m_isEnabled.load(std::memory_order_acquire);
|
||||
const bool eventTracingEnabled = m_isEventTracingEnabled.load(std::memory_order_acquire);
|
||||
if (wasEnabled)
|
||||
::profiler::setEnabled(false);
|
||||
|
||||
|
@ -369,6 +369,7 @@ public:
|
||||
void beginBlock(profiler::Block& _block);
|
||||
void endBlock();
|
||||
void setEnabled(bool isEnable);
|
||||
void setEventTracingEnabled(bool _isEnable);
|
||||
uint32_t dumpBlocksToFile(const char* filename);
|
||||
const char* registerThread(const char* name);// , const char* filename, const char* _funcname, int line);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user