mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 00:31:02 +08:00
1) Removed Mark entity. Only Block with type
2) Added simple implementation of serializing blocks and storing it.
This commit is contained in:
parent
d12ff7fb67
commit
9cf3ca02b7
@ -27,16 +27,16 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FULL_DISABLE_PROFILER
|
#ifndef FULL_DISABLE_PROFILER
|
||||||
#define PROFILER_ADD_MARK(name) profiler::Mark TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name);\
|
#define PROFILER_ADD_MARK(name) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,0,profiler::BLOCK_TYPE_MARK);\
|
||||||
profiler::registerMark(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
|
||||||
|
|
||||||
#define PROFILER_ADD_MARK_GROUPED(name,block_group) profiler::Mark TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,block_group);\
|
|
||||||
profiler::registerMark(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
|
||||||
|
|
||||||
#define PROFILER_BEGIN_BLOCK(name) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name);\
|
|
||||||
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
||||||
|
|
||||||
#define PROFILER_BEGIN_BLOCK_GROUPED(name,block_group) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,block_group);\
|
#define PROFILER_ADD_MARK_GROUPED(name,block_group) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,block_group,profiler::BLOCK_TYPE_MARK);\
|
||||||
|
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
||||||
|
|
||||||
|
#define PROFILER_BEGIN_BLOCK(name) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,0,profiler::BLOCK_TYPE_BLOCK);\
|
||||||
|
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
||||||
|
|
||||||
|
#define PROFILER_BEGIN_BLOCK_GROUPED(name,block_group) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,block_group,profiler::BLOCK_TYPE_BLOCK);\
|
||||||
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
profiler::beginBlock(&TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__));
|
||||||
|
|
||||||
#define PROFILER_BEGIN_FUNCTION_BLOCK PROFILER_BEGIN_BLOCK(__func__)
|
#define PROFILER_BEGIN_FUNCTION_BLOCK PROFILER_BEGIN_BLOCK(__func__)
|
||||||
@ -76,32 +76,42 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace profiler
|
namespace profiler
|
||||||
{
|
{
|
||||||
class Mark;
|
|
||||||
class Block;
|
class Block;
|
||||||
|
|
||||||
extern "C"{
|
extern "C"{
|
||||||
void PROFILER_API registerMark(Mark* _mark);
|
|
||||||
void PROFILER_API beginBlock(Block* _block);
|
void PROFILER_API beginBlock(Block* _block);
|
||||||
void PROFILER_API endBlock();
|
void PROFILER_API endBlock();
|
||||||
void PROFILER_API setEnabled(bool isEnable);
|
void PROFILER_API setEnabled(bool isEnable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef uint8_t block_type_t;
|
||||||
typedef uint64_t timestamp_t;
|
typedef uint64_t timestamp_t;
|
||||||
typedef unsigned char color_t;
|
typedef uint16_t color_t;
|
||||||
|
typedef uint32_t thread_id_t;
|
||||||
|
|
||||||
class PROFILER_API Mark
|
const block_type_t BLOCK_TYPE_MARK = 1;
|
||||||
|
const block_type_t BLOCK_TYPE_BLOCK = 2;
|
||||||
|
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct PROFILER_API BaseBlockData
|
||||||
|
{
|
||||||
|
block_type_t type;
|
||||||
|
color_t color;
|
||||||
|
timestamp_t begin;
|
||||||
|
timestamp_t end;
|
||||||
|
thread_id_t thread_id;
|
||||||
|
|
||||||
|
BaseBlockData(color_t _color, block_type_t _type);
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
class PROFILER_API Block : public BaseBlockData
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
unsigned char type;
|
|
||||||
color_t color;
|
|
||||||
timestamp_t begin;
|
|
||||||
size_t thread_id;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
void tick(timestamp_t& stamp);
|
void tick(timestamp_t& stamp);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Mark(const char* _name, color_t _color = 0);
|
Block(const char* _name, color_t _color = 0, block_type_t _type = BLOCK_TYPE_MARK);
|
||||||
|
|
||||||
inline unsigned char getType() const { return type; }
|
inline unsigned char getType() const { return type; }
|
||||||
inline color_t getColor() const { return color; }
|
inline color_t getColor() const { return color; }
|
||||||
@ -109,19 +119,13 @@ namespace profiler
|
|||||||
inline size_t getThreadId() const { return thread_id; }
|
inline size_t getThreadId() const { return thread_id; }
|
||||||
inline const char* getName() const { return name; }
|
inline const char* getName() const { return name; }
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class PROFILER_API Block : public Mark
|
|
||||||
{
|
|
||||||
timestamp_t end;
|
|
||||||
public:
|
|
||||||
Block(const char* _name, color_t _color = 0);
|
|
||||||
~Block();
|
|
||||||
|
|
||||||
inline timestamp_t getEnd() const { return end; }
|
inline timestamp_t getEnd() const { return end; }
|
||||||
inline bool isFinished() const { return end != 0; }
|
inline bool isFinished() const { return end != 0; }
|
||||||
inline bool isCleared() const { return end >= begin; }
|
inline bool isCleared() const { return end >= begin; }
|
||||||
inline void finish(){ tick(end); }
|
inline void finish(){ tick(end); }
|
||||||
|
|
||||||
|
~Block();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,44 +6,41 @@
|
|||||||
|
|
||||||
using namespace profiler;
|
using namespace profiler;
|
||||||
|
|
||||||
const int NAME_LENGTH = 64;
|
BaseBlockData::BaseBlockData(color_t _color, block_type_t _type) :
|
||||||
|
type(_type),
|
||||||
const unsigned char MARK_TYPE_LOCAL_EVENT = 1;
|
|
||||||
const unsigned char MARK_TYPE_GLOBAL_EVENT = 2;
|
|
||||||
const unsigned char MARK_TYPE_BEGIN = 3;
|
|
||||||
const unsigned char MARK_TYPE_END = 4;
|
|
||||||
|
|
||||||
Mark::Mark(const char* _name, color_t _color) :
|
|
||||||
type(0),
|
|
||||||
color(_color),
|
color(_color),
|
||||||
begin(0),
|
begin(0),
|
||||||
thread_id(0),
|
end(0),
|
||||||
|
thread_id(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Block::Block(const char* _name, color_t _color, block_type_t _type) :
|
||||||
|
BaseBlockData(_color,_type),
|
||||||
name(_name)
|
name(_name)
|
||||||
{
|
{
|
||||||
tick(begin);
|
tick(begin);
|
||||||
thread_id = std::hash<std::thread::id>()(std::this_thread::get_id());
|
thread_id = std::hash<std::thread::id>()(std::this_thread::get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mark::tick(timestamp_t& stamp)
|
void Block::tick(timestamp_t& stamp)
|
||||||
{
|
{
|
||||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> time_point;
|
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> time_point;
|
||||||
time_point = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now());
|
time_point = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now());
|
||||||
stamp = time_point.time_since_epoch().count();
|
stamp = time_point.time_since_epoch().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
Block::Block(const char* _name, color_t _color) :
|
|
||||||
Mark(_name, _color),
|
|
||||||
end(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Block::~Block()
|
Block::~Block()
|
||||||
{
|
{
|
||||||
if (this->isCleared())
|
if (this->type == BLOCK_TYPE_BLOCK)
|
||||||
return;
|
{
|
||||||
if (!this->isFinished())
|
if (this->isCleared())//this block was cleared by END_BLOCK macros
|
||||||
this->finish();
|
return;
|
||||||
|
if (!this->isFinished())
|
||||||
|
this->finish();
|
||||||
|
|
||||||
endBlock();
|
endBlock();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,6 @@ using namespace profiler;
|
|||||||
|
|
||||||
extern "C"{
|
extern "C"{
|
||||||
|
|
||||||
void PROFILER_API registerMark(Mark* _mark)
|
|
||||||
{
|
|
||||||
ProfileManager::instance().registerMark(_mark);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PROFILER_API endBlock()
|
void PROFILER_API endBlock()
|
||||||
{
|
{
|
||||||
ProfileManager::instance().endBlock();
|
ProfileManager::instance().endBlock();
|
||||||
@ -26,12 +21,41 @@ extern "C"{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SerilizedBlock::SerilizedBlock(Block* block):
|
||||||
|
m_size(0),
|
||||||
|
m_data(nullptr)
|
||||||
|
{
|
||||||
|
m_size += sizeof(BaseBlockData);
|
||||||
|
auto name_len = strlen(block->getName()) + 1;
|
||||||
|
m_size += name_len;
|
||||||
|
|
||||||
|
m_data = new char[m_size];
|
||||||
|
memcpy(&m_data[0], block, sizeof(BaseBlockData));
|
||||||
|
strncpy(&m_data[sizeof(BaseBlockData)], block->getName(), name_len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SerilizedBlock::~SerilizedBlock()
|
||||||
|
{
|
||||||
|
if (m_data){
|
||||||
|
delete[] m_data;
|
||||||
|
m_data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ProfileManager::ProfileManager()
|
ProfileManager::ProfileManager()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProfileManager::~ProfileManager()
|
||||||
|
{
|
||||||
|
for (auto* b : m_blocks){
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProfileManager& ProfileManager::instance()
|
ProfileManager& ProfileManager::instance()
|
||||||
{
|
{
|
||||||
///C++11 makes possible to create Singleton without any warry about thread-safeness
|
///C++11 makes possible to create Singleton without any warry about thread-safeness
|
||||||
@ -40,19 +64,18 @@ ProfileManager& ProfileManager::instance()
|
|||||||
return m_profileManager;
|
return m_profileManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::registerMark(Mark* _mark)
|
|
||||||
{
|
|
||||||
if (!m_isEnabled)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileManager::beginBlock(Block* _block)
|
void ProfileManager::beginBlock(Block* _block)
|
||||||
{
|
{
|
||||||
if (!m_isEnabled)
|
if (!m_isEnabled)
|
||||||
return;
|
return;
|
||||||
|
if (_block->getType() != BLOCK_TYPE_MARK){
|
||||||
guard_lock_t lock(m_spin);
|
guard_lock_t lock(m_spin);
|
||||||
m_openedBracketsMap[_block->getThreadId()].push(_block);
|
m_openedBracketsMap[_block->getThreadId()].push(_block);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_internalInsertBlock(_block);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::endBlock()
|
void ProfileManager::endBlock()
|
||||||
@ -73,6 +96,7 @@ void ProfileManager::endBlock()
|
|||||||
if (lastBlock && !lastBlock->isFinished()){
|
if (lastBlock && !lastBlock->isFinished()){
|
||||||
lastBlock->finish();
|
lastBlock->finish();
|
||||||
}
|
}
|
||||||
|
_internalInsertBlock(lastBlock);
|
||||||
stackOfOpenedBlocks.pop();
|
stackOfOpenedBlocks.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,3 +104,9 @@ void ProfileManager::setEnabled(bool isEnable)
|
|||||||
{
|
{
|
||||||
m_isEnabled = isEnable;
|
m_isEnabled = isEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfileManager::_internalInsertBlock(profiler::Block* _block)
|
||||||
|
{
|
||||||
|
guard_lock_t lock(m_storedSpin);
|
||||||
|
m_blocks.emplace_back(new SerilizedBlock(_block));
|
||||||
|
}
|
@ -25,6 +25,20 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class SerilizedBlock
|
||||||
|
{
|
||||||
|
uint16_t m_size;
|
||||||
|
char* m_data;
|
||||||
|
public:
|
||||||
|
|
||||||
|
SerilizedBlock(profiler::Block* block);
|
||||||
|
~SerilizedBlock();
|
||||||
|
|
||||||
|
const char* const data() { return m_data; }
|
||||||
|
uint16_t size() const { return m_size; }
|
||||||
|
};
|
||||||
|
|
||||||
class ProfileManager
|
class ProfileManager
|
||||||
{
|
{
|
||||||
@ -41,11 +55,16 @@ class ProfileManager
|
|||||||
map_of_threads_stacks m_openedBracketsMap;
|
map_of_threads_stacks m_openedBracketsMap;
|
||||||
|
|
||||||
profiler::spin_lock m_spin;
|
profiler::spin_lock m_spin;
|
||||||
|
profiler::spin_lock m_storedSpin;
|
||||||
typedef profiler::guard_lock<profiler::spin_lock> guard_lock_t;
|
typedef profiler::guard_lock<profiler::spin_lock> guard_lock_t;
|
||||||
|
|
||||||
|
void _internalInsertBlock(profiler::Block* _block);
|
||||||
|
|
||||||
|
typedef std::list<SerilizedBlock*> serialized_list_t;
|
||||||
|
serialized_list_t m_blocks;
|
||||||
public:
|
public:
|
||||||
static ProfileManager& instance();
|
static ProfileManager& instance();
|
||||||
|
~ProfileManager();
|
||||||
void registerMark(profiler::Mark* _mark);
|
|
||||||
void beginBlock(profiler::Block* _block);
|
void beginBlock(profiler::Block* _block);
|
||||||
void endBlock();
|
void endBlock();
|
||||||
void setEnabled(bool isEnable);
|
void setEnabled(bool isEnable);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user