mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 08:41:02 +08:00
(Core) Monitoring threads, removing threads without blocks, events and context switches;
* (Core) Context switch events also register threads for current process; * (Core) Writing process id into output file (old files still could be opened);
This commit is contained in:
parent
039e0a6efa
commit
29f81d1244
@ -1,4 +1,4 @@
|
||||
# easy_profiler [![version](https://img.shields.io/badge/version-1.0.0%20beta-009688.svg)](https://github.com/yse/easy_profiler/releases)
|
||||
# easy_profiler [![version](https://img.shields.io/badge/version-1.0.1%20beta-009688.svg)](https://github.com/yse/easy_profiler/releases)
|
||||
|
||||
[![Build Status](https://travis-ci.org/yse/easy_profiler.svg?branch=develop)](https://travis-ci.org/yse/easy_profiler)
|
||||
|
||||
|
@ -129,6 +129,7 @@ namespace profiler {
|
||||
if (time > TRACING_END_TIME.load(::std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
processid_t pid = 0;
|
||||
const char* process_name = "";
|
||||
|
||||
// Trying to get target process name and id
|
||||
@ -138,7 +139,7 @@ namespace profiler {
|
||||
auto hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, _contextSwitchEvent->NewThreadId);
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
auto pid = GetProcessIdOfThread(hThread);
|
||||
pid = GetProcessIdOfThread(hThread);
|
||||
auto pinfo = &PROCESS_INFO_TABLE[pid];
|
||||
|
||||
if (pinfo->valid == 0)
|
||||
@ -204,7 +205,7 @@ namespace profiler {
|
||||
}
|
||||
|
||||
MANAGER.beginContextSwitch(_contextSwitchEvent->OldThreadId, time, _contextSwitchEvent->NewThreadId, process_name);
|
||||
MANAGER.endContextSwitch(_contextSwitchEvent->NewThreadId, time);
|
||||
MANAGER.endContextSwitch(_contextSwitchEvent->NewThreadId, pid, time);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -196,9 +196,10 @@ namespace profiler {
|
||||
std::string thread_name; ///< Name of this thread
|
||||
::profiler::timestamp_t active_time; ///< Active time of this thread (sum of all children duration)
|
||||
::profiler::thread_id_t thread_id; ///< System Id of this thread
|
||||
::profiler::block_index_t blocks_number; ///< Total blocks number including their children
|
||||
uint16_t depth; ///< Maximum stack depth (number of levels)
|
||||
|
||||
BlocksTreeRoot() : active_time(0), thread_id(0), depth(0)
|
||||
BlocksTreeRoot() : active_time(0), thread_id(0), blocks_number(0), depth(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -209,6 +210,7 @@ namespace profiler {
|
||||
, thread_name(::std::move(that.thread_name))
|
||||
, active_time(that.active_time)
|
||||
, thread_id(that.thread_id)
|
||||
, blocks_number(that.blocks_number)
|
||||
, depth(that.depth)
|
||||
{
|
||||
}
|
||||
@ -221,6 +223,7 @@ namespace profiler {
|
||||
thread_name = ::std::move(that.thread_name);
|
||||
active_time = that.active_time;
|
||||
thread_id = that.thread_id;
|
||||
blocks_number = that.blocks_number;
|
||||
depth = that.depth;
|
||||
return *this;
|
||||
}
|
||||
|
@ -47,9 +47,8 @@
|
||||
#include "event_trace_win.h"
|
||||
#include "current_time.h"
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -93,20 +92,34 @@ EASY_THREAD_LOCAL static ::ThreadStorage* THREAD_STORAGE = nullptr;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef BUILD_WITH_EASY_PROFILER
|
||||
# define EASY_EVENT_RES(res, name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), MANAGER.addBlockDescriptor(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BLOCK_TYPE_EVENT, ::profiler::extract_color(__VA_ARGS__)));\
|
||||
res = MANAGER.storeBlock(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name))
|
||||
|
||||
# define EASY_FORCE_EVENT(timestamp, name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), addBlockDescriptor(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BLOCK_TYPE_EVENT, ::profiler::extract_color(__VA_ARGS__)));\
|
||||
storeBlockForce(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name), timestamp);
|
||||
storeBlockForce(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name), timestamp)
|
||||
|
||||
# define EASY_FORCE_EVENT2(timestamp, name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), addBlockDescriptor(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BLOCK_TYPE_EVENT, ::profiler::extract_color(__VA_ARGS__)));\
|
||||
storeBlockForce2(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name), timestamp);
|
||||
storeBlockForce2(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name), timestamp)
|
||||
|
||||
# define EASY_FORCE_EVENT3(ts, timestamp, name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), addBlockDescriptor(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BLOCK_TYPE_EVENT, ::profiler::extract_color(__VA_ARGS__)));\
|
||||
storeBlockForce2(ts, EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name), timestamp)
|
||||
#else
|
||||
# define EASY_EVENT_RES(res, name, ...)
|
||||
# define EASY_FORCE_EVENT(timestamp, name, ...)
|
||||
# define EASY_FORCE_EVENT2(timestamp, name, ...)
|
||||
# define EASY_FORCE_EVENT3(ts, timestamp, name, ...)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -314,14 +327,13 @@ public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ThreadStorage::ThreadStorage() : id(getCurrentThreadId()), allowChildren(true), named(false)
|
||||
ThreadStorage::ThreadStorage() : id(getCurrentThreadId()), allowChildren(true), named(false), guarded(false)
|
||||
#ifndef _WIN32
|
||||
, pthread_id(pthread_self())
|
||||
#endif
|
||||
|
||||
{
|
||||
expired = ATOMIC_VAR_INIT(false);
|
||||
|
||||
expired = ATOMIC_VAR_INIT(0);
|
||||
}
|
||||
|
||||
void ThreadStorage::storeBlock(const profiler::Block& block)
|
||||
@ -388,8 +400,9 @@ ThreadGuard::~ThreadGuard()
|
||||
#ifndef EASY_PROFILER_API_DISABLED
|
||||
if (m_id != 0 && THREAD_STORAGE != nullptr && THREAD_STORAGE->id == m_id)
|
||||
{
|
||||
EASY_EVENT("ThreadFinished", profiler::colors::Dark);
|
||||
THREAD_STORAGE->expired.store(true, std::memory_order_release);
|
||||
bool isMarked = false;
|
||||
EASY_EVENT_RES(isMarked, "ThreadFinished", profiler::colors::Dark, ::profiler::FORCE_ON);
|
||||
THREAD_STORAGE->expired.store(isMarked ? 2 : 1, std::memory_order_release);
|
||||
THREAD_STORAGE = nullptr;
|
||||
}
|
||||
#endif
|
||||
@ -397,7 +410,15 @@ ThreadGuard::~ThreadGuard()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProfileManager::ProfileManager()
|
||||
ProfileManager::ProfileManager() :
|
||||
#ifdef _WIN32
|
||||
m_processId(GetProcessId(GetCurrentProcess()))
|
||||
#else
|
||||
m_processId((processid_t)getpid())
|
||||
#endif
|
||||
, m_usedMemorySize(0)
|
||||
, m_beginTime(0)
|
||||
, m_endTime(0)
|
||||
{
|
||||
m_isEnabled = ATOMIC_VAR_INIT(false);
|
||||
m_isEventTracingEnabled = ATOMIC_VAR_INIT(EASY_EVENT_TRACING_ENABLED);
|
||||
@ -422,6 +443,8 @@ class ProfileManagerInstance {
|
||||
} PROFILE_MANAGER;
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProfileManager& ProfileManager::instance()
|
||||
{
|
||||
#ifndef EASY_MAGIC_STATIC_CPP11
|
||||
@ -434,9 +457,10 @@ ProfileManager& ProfileManager::instance()
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadStorage& ProfileManager::threadStorage(profiler::thread_id_t _thread_id)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ThreadStorage& ProfileManager::_threadStorage(profiler::thread_id_t _thread_id)
|
||||
{
|
||||
guard_lock_t lock(m_spin);
|
||||
return m_threads[_thread_id];
|
||||
}
|
||||
|
||||
@ -446,6 +470,8 @@ ThreadStorage* ProfileManager::_findThreadStorage(profiler::thread_id_t _thread_
|
||||
return it != m_threads.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _defaultStatus,
|
||||
const char* _autogenUniqueId,
|
||||
const char* _name,
|
||||
@ -469,17 +495,19 @@ const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _d
|
||||
return desc;
|
||||
}
|
||||
|
||||
void ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
||||
{
|
||||
if (!m_isEnabled.load(std::memory_order_acquire) || !(_desc->m_status & profiler::ON))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (THREAD_STORAGE == nullptr)
|
||||
THREAD_STORAGE = &threadStorage(getCurrentThreadId());
|
||||
|
||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||
if (!THREAD_STORAGE->allowChildren)
|
||||
return;
|
||||
if (!THREAD_STORAGE->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
profiler::Block b(_desc, _runtimeName);
|
||||
@ -487,8 +515,12 @@ void ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, cons
|
||||
b.m_end = b.m_begin;
|
||||
|
||||
THREAD_STORAGE->storeBlock(b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProfileManager::storeBlockForce(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t& _timestamp)
|
||||
{
|
||||
if (!(_desc->m_status & profiler::ON))
|
||||
@ -498,7 +530,7 @@ void ProfileManager::storeBlockForce(const profiler::BaseBlockDescriptor* _desc,
|
||||
THREAD_STORAGE = &threadStorage(getCurrentThreadId());
|
||||
|
||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||
if (!THREAD_STORAGE->allowChildren)
|
||||
if (!THREAD_STORAGE->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
||||
return;
|
||||
#endif
|
||||
|
||||
@ -519,7 +551,7 @@ void ProfileManager::storeBlockForce2(const profiler::BaseBlockDescriptor* _desc
|
||||
THREAD_STORAGE = &threadStorage(getCurrentThreadId());
|
||||
|
||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||
if (!THREAD_STORAGE->allowChildren)
|
||||
if (!THREAD_STORAGE->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
||||
return;
|
||||
#endif
|
||||
|
||||
@ -529,6 +561,15 @@ void ProfileManager::storeBlockForce2(const profiler::BaseBlockDescriptor* _desc
|
||||
THREAD_STORAGE->storeBlock(b);
|
||||
}
|
||||
|
||||
void ProfileManager::storeBlockForce2(ThreadStorage& _registeredThread, const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t _timestamp)
|
||||
{
|
||||
profiler::Block b(_desc, _runtimeName);
|
||||
b.m_end = b.m_begin = _timestamp;
|
||||
_registeredThread.storeBlock(b);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProfileManager::beginBlock(Block& _block)
|
||||
{
|
||||
if (!m_isEnabled.load(std::memory_order_acquire))
|
||||
@ -569,16 +610,7 @@ void ProfileManager::beginContextSwitch(profiler::thread_id_t _thread_id, profil
|
||||
ts->sync.openedList.emplace(_time, _target_thread_id, _target_process);
|
||||
}
|
||||
|
||||
void ProfileManager::storeContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, bool _lockSpin)
|
||||
{
|
||||
auto ts = _lockSpin ? findThreadStorage(_thread_id) : _findThreadStorage(_thread_id);
|
||||
if (ts != nullptr)
|
||||
{
|
||||
profiler::Block b(_time, _target_thread_id, "");
|
||||
b.finish(_time);
|
||||
ts->storeCSwitch(b);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProfileManager::endBlock()
|
||||
{
|
||||
@ -607,9 +639,16 @@ void ProfileManager::endBlock()
|
||||
#endif
|
||||
}
|
||||
|
||||
void ProfileManager::endContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _endtime, bool _lockSpin)
|
||||
void ProfileManager::endContextSwitch(profiler::thread_id_t _thread_id, processid_t _process_id, profiler::timestamp_t _endtime, bool _lockSpin)
|
||||
{
|
||||
auto ts = _lockSpin ? findThreadStorage(_thread_id) : _findThreadStorage(_thread_id);
|
||||
ThreadStorage* ts = nullptr;
|
||||
if (_process_id == m_processId)
|
||||
// If thread owned by current process then create new ThreadStorage if there is no one
|
||||
ts = _lockSpin ? &threadStorage(_thread_id) : &_threadStorage(_thread_id);
|
||||
else
|
||||
// If thread owned by another process OR _process_id IS UNKNOWN then do not create ThreadStorage for this
|
||||
ts = _lockSpin ? findThreadStorage(_thread_id) : _findThreadStorage(_thread_id);
|
||||
|
||||
if (ts == nullptr || ts->sync.openedList.empty())
|
||||
return;
|
||||
|
||||
@ -620,6 +659,8 @@ void ProfileManager::endContextSwitch(profiler::thread_id_t _thread_id, profiler
|
||||
ts->sync.openedList.pop();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProfileManager::setEnabled(bool isEnable, bool _setTime)
|
||||
{
|
||||
auto time = getCurrentTime();
|
||||
@ -661,10 +702,14 @@ void ProfileManager::setEventTracingEnabled(bool _isEnable)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ProfileManager::checkThreadExpired(ThreadStorage& _registeredThread)
|
||||
uint8_t ProfileManager::checkThreadExpired(ThreadStorage& _registeredThread)
|
||||
{
|
||||
if (_registeredThread.expired.load(std::memory_order_acquire))
|
||||
return true;
|
||||
const uint8_t val = _registeredThread.expired.load(std::memory_order_acquire);
|
||||
if (val != 0)
|
||||
return val;
|
||||
|
||||
if (_registeredThread.guarded)
|
||||
return 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@ -678,19 +723,20 @@ bool ProfileManager::checkThreadExpired(ThreadStorage& _registeredThread)
|
||||
_registeredThread.expired.store(true, std::memory_order_release);
|
||||
if (hThread != nullptr)
|
||||
CloseHandle(hThread);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hThread != nullptr)
|
||||
CloseHandle(hThread);
|
||||
return false;
|
||||
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return false;//pthread_kill(_registeredThread.pthread_id, 0) != 0;
|
||||
return 0;//pthread_kill(_registeredThread.pthread_id, 0) != 0;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -719,6 +765,8 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
// TODO: think about better solution because this one is not 100% safe...
|
||||
|
||||
const profiler::timestamp_t now = getCurrentTime();
|
||||
const profiler::timestamp_t endtime = m_endTime == 0 ? now : std::min(now, m_endTime);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (eventTracingEnabled)
|
||||
@ -731,9 +779,10 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
std::ifstream infile(m_csInfoFilename.c_str());
|
||||
if(infile.is_open()) {
|
||||
std::string next_task_name;
|
||||
while (infile >> timestamp >> thread_from >> thread_to >> next_task_name) {
|
||||
pid_t process_to = 0;
|
||||
while (infile >> timestamp >> thread_from >> thread_to >> next_task_name >> process_to) {
|
||||
beginContextSwitch(thread_from, timestamp, thread_to, next_task_name.c_str(), false);
|
||||
endContextSwitch(thread_to, timestamp, false);
|
||||
endContextSwitch(thread_to, (processid_t)process_to, timestamp, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -745,16 +794,20 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
for (auto it = m_threads.begin(), end = m_threads.end(); it != end;)
|
||||
{
|
||||
auto& t = it->second;
|
||||
const uint32_t num = static_cast<uint32_t>(t.blocks.closedList.size()) + static_cast<uint32_t>(t.sync.closedList.size());
|
||||
uint32_t num = static_cast<uint32_t>(t.blocks.closedList.size()) + static_cast<uint32_t>(t.sync.closedList.size());
|
||||
|
||||
const bool expired = checkThreadExpired(t) || t.expired.load(std::memory_order_acquire);
|
||||
if (expired && num == 0) {
|
||||
// Thread has been finished and contains no profiled information.
|
||||
// Remove it now.
|
||||
const uint8_t expired = checkThreadExpired(t);
|
||||
if (num == 0 && (expired != 0 || !t.guarded)) {
|
||||
// Remove thread if it contains no profiled information and has been finished or is not guarded.
|
||||
m_threads.erase(it++);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expired == 1) {
|
||||
EASY_FORCE_EVENT3(t, endtime, "ThreadExpired", profiler::colors::Dark);
|
||||
++num;
|
||||
}
|
||||
|
||||
usedMemorySize += t.blocks.usedMemorySize + t.sync.usedMemorySize;
|
||||
blocks_number += num;
|
||||
++it;
|
||||
@ -763,6 +816,7 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
// Write profiler signature and version
|
||||
_outputStream.write(PROFILER_SIGNATURE);
|
||||
_outputStream.write(EASY_CURRENT_VERSION);
|
||||
_outputStream.write(m_processId);
|
||||
|
||||
// Write CPU frequency to let GUI calculate real time value from CPU clocks
|
||||
#ifdef _WIN32
|
||||
@ -847,7 +901,7 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream)
|
||||
t.blocks.openedList.clear();
|
||||
t.sync.openedList.clear();
|
||||
|
||||
if (t.expired.load(std::memory_order_acquire))
|
||||
if (t.expired.load(std::memory_order_acquire) != 0)
|
||||
m_threads.erase(it++); // Remove expired thread after writing all profiled information
|
||||
else
|
||||
++it;
|
||||
@ -875,6 +929,7 @@ const char* ProfileManager::registerThread(const char* name, ThreadGuard& thread
|
||||
if (THREAD_STORAGE == nullptr)
|
||||
THREAD_STORAGE = &threadStorage(getCurrentThreadId());
|
||||
|
||||
THREAD_STORAGE->guarded = true;
|
||||
if (!THREAD_STORAGE->named) {
|
||||
THREAD_STORAGE->named = true;
|
||||
THREAD_STORAGE->name = name;
|
||||
|
@ -320,9 +320,10 @@ struct ThreadStorage
|
||||
#endif
|
||||
|
||||
const profiler::thread_id_t id;
|
||||
std::atomic_bool expired;
|
||||
std::atomic<uint8_t> expired;
|
||||
bool allowChildren;
|
||||
bool named;
|
||||
bool guarded;
|
||||
|
||||
void storeBlock(const profiler::Block& _block);
|
||||
void storeCSwitch(const profiler::Block& _block);
|
||||
@ -333,6 +334,8 @@ struct ThreadStorage
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint32_t processid_t;
|
||||
|
||||
class BlockDescriptor;
|
||||
|
||||
class ProfileManager
|
||||
@ -355,12 +358,14 @@ class ProfileManager
|
||||
typedef std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t> descriptors_map_t;
|
||||
#endif
|
||||
|
||||
const processid_t m_processId;
|
||||
|
||||
map_of_threads_stacks m_threads;
|
||||
block_descriptors_t m_descriptors;
|
||||
descriptors_map_t m_descriptorsMap;
|
||||
uint64_t m_usedMemorySize = 0;
|
||||
profiler::timestamp_t m_beginTime = 0;
|
||||
profiler::timestamp_t m_endTime = 0;
|
||||
uint64_t m_usedMemorySize;
|
||||
profiler::timestamp_t m_beginTime;
|
||||
profiler::timestamp_t m_endTime;
|
||||
profiler::spin_lock m_spin;
|
||||
profiler::spin_lock m_storedSpin;
|
||||
std::atomic_bool m_isEnabled;
|
||||
@ -392,7 +397,7 @@ public:
|
||||
profiler::block_type_t _block_type,
|
||||
profiler::color_t _color);
|
||||
|
||||
void storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
|
||||
bool storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
|
||||
void beginBlock(profiler::Block& _block);
|
||||
void endBlock();
|
||||
void setEnabled(bool isEnable, bool _setTime = true);
|
||||
@ -412,22 +417,28 @@ public:
|
||||
}
|
||||
|
||||
void beginContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, const char* _target_process, bool _lockSpin = true);
|
||||
void storeContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, bool _lockSpin = true);
|
||||
void endContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _endtime, bool _lockSpin = true);
|
||||
void endContextSwitch(profiler::thread_id_t _thread_id, processid_t _process_id, profiler::timestamp_t _endtime, bool _lockSpin = true);
|
||||
void startListen(uint16_t _port);
|
||||
void stopListen();
|
||||
|
||||
private:
|
||||
|
||||
bool checkThreadExpired(ThreadStorage& _registeredThread);
|
||||
uint8_t checkThreadExpired(ThreadStorage& _registeredThread);
|
||||
|
||||
void storeBlockForce(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t& _timestamp);
|
||||
void storeBlockForce2(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t _timestamp);
|
||||
void storeBlockForce2(ThreadStorage& _registeredThread, const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t _timestamp);
|
||||
|
||||
ThreadStorage& threadStorage(profiler::thread_id_t _thread_id);
|
||||
ThreadStorage& _threadStorage(profiler::thread_id_t _thread_id);
|
||||
ThreadStorage* _findThreadStorage(profiler::thread_id_t _thread_id);
|
||||
|
||||
ThreadStorage* findThreadStorage(profiler::thread_id_t _thread_id)
|
||||
inline ThreadStorage& threadStorage(profiler::thread_id_t _thread_id)
|
||||
{
|
||||
guard_lock_t lock(m_spin);
|
||||
return _threadStorage(_thread_id);
|
||||
}
|
||||
|
||||
inline ThreadStorage* findThreadStorage(profiler::thread_id_t _thread_id)
|
||||
{
|
||||
guard_lock_t lock(m_spin);
|
||||
return _findThreadStorage(_thread_id);
|
||||
|
@ -67,14 +67,18 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint32_t processid_t;
|
||||
|
||||
extern const uint32_t PROFILER_SIGNATURE;
|
||||
extern const uint32_t EASY_CURRENT_VERSION;
|
||||
|
||||
# define EASY_VERSION_INT(v_major, v_minor, v_patch) ((static_cast<uint32_t>(v_major) << 24) | (static_cast<uint32_t>(v_minor) << 16) | static_cast<uint32_t>(v_patch))
|
||||
const uint32_t EASY_V_100 = EASY_VERSION_INT(1, 0, 0);
|
||||
const uint32_t COMPATIBLE_VERSIONS[] = {
|
||||
EASY_CURRENT_VERSION,
|
||||
EASY_V_100,
|
||||
EASY_VERSION_INT(0, 1, 0)
|
||||
};
|
||||
// WARNING: Modify isCompatibleVersion(uint32_t _version) if COMPATIBLE_VERSIONS_NUM == 0
|
||||
const uint16_t COMPATIBLE_VERSIONS_NUM = sizeof(COMPATIBLE_VERSIONS) / sizeof(uint32_t);
|
||||
# undef EASY_VERSION_INT
|
||||
|
||||
@ -112,7 +116,9 @@ bool isCompatibleVersion(uint32_t _version)
|
||||
{
|
||||
if (_version == EASY_CURRENT_VERSION)
|
||||
return true;
|
||||
return COMPATIBLE_VERSIONS_NUM > 1 && ::std::binary_search(COMPATIBLE_VERSIONS + 1, COMPATIBLE_VERSIONS + COMPATIBLE_VERSIONS_NUM, _version);
|
||||
|
||||
return ::std::binary_search(COMPATIBLE_VERSIONS, COMPATIBLE_VERSIONS + COMPATIBLE_VERSIONS_NUM,
|
||||
_version, [](uint32_t _a, uint32_t _b){ return _a > _b; });
|
||||
}
|
||||
|
||||
inline void write(::std::stringstream& _stream, const char* _value, size_t _size)
|
||||
@ -369,6 +375,10 @@ extern "C" {
|
||||
return 0;
|
||||
}
|
||||
|
||||
processid_t pid = 0;
|
||||
if (version > EASY_V_100)
|
||||
inFile.read((char*)&pid, sizeof(processid_t));
|
||||
|
||||
int64_t file_cpu_frequency = 0LL;
|
||||
inFile.read((char*)&file_cpu_frequency, sizeof(int64_t));
|
||||
uint64_t cpu_frequency = file_cpu_frequency;
|
||||
@ -669,6 +679,7 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
|
||||
++root.blocks_number;
|
||||
root.children.emplace_back(block_index);// ::std::move(tree));
|
||||
if (desc->type() == ::profiler::BLOCK_TYPE_EVENT)
|
||||
root.events.emplace_back(block_index);
|
||||
|
@ -1 +1 @@
|
||||
1.0.0
|
||||
1.0.1
|
Loading…
x
Reference in New Issue
Block a user