0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-26 08:01:51 +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:
Sergey Yagovtsev 2016-02-20 05:24:12 +03:00
parent d12ff7fb67
commit 9cf3ca02b7
4 changed files with 117 additions and 67 deletions

View File

@ -27,16 +27,16 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
#endif
#ifndef FULL_DISABLE_PROFILER
#define PROFILER_ADD_MARK(name) profiler::Mark TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name);\
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);\
#define PROFILER_ADD_MARK(name) profiler::Block TOKEN_CONCATENATE(unique_profiler_mark_name_,__LINE__)(name,0,profiler::BLOCK_TYPE_MARK);\
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__));
#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
{
class Mark;
class Block;
extern "C"{
void PROFILER_API registerMark(Mark* _mark);
void PROFILER_API beginBlock(Block* _block);
void PROFILER_API endBlock();
void PROFILER_API setEnabled(bool isEnable);
}
typedef uint8_t block_type_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;
void tick(timestamp_t& stamp);
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 color_t getColor() const { return color; }
@ -109,19 +119,13 @@ namespace profiler
inline size_t getThreadId() const { return thread_id; }
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 bool isFinished() const { return end != 0; }
inline bool isCleared() const { return end >= begin; }
inline void finish(){ tick(end); }
~Block();
};
}

View File

@ -6,44 +6,41 @@
using namespace profiler;
const int NAME_LENGTH = 64;
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),
BaseBlockData::BaseBlockData(color_t _color, block_type_t _type) :
type(_type),
color(_color),
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)
{
tick(begin);
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;
time_point = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now());
stamp = time_point.time_since_epoch().count();
}
Block::Block(const char* _name, color_t _color) :
Mark(_name, _color),
end(0)
{
}
Block::~Block()
{
if (this->isCleared())
return;
if (!this->isFinished())
this->finish();
if (this->type == BLOCK_TYPE_BLOCK)
{
if (this->isCleared())//this block was cleared by END_BLOCK macros
return;
if (!this->isFinished())
this->finish();
endBlock();
endBlock();
}
}

View File

@ -6,11 +6,6 @@ using namespace profiler;
extern "C"{
void PROFILER_API registerMark(Mark* _mark)
{
ProfileManager::instance().registerMark(_mark);
}
void PROFILER_API 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()
{
for (auto* b : m_blocks){
delete b;
}
}
ProfileManager& ProfileManager::instance()
{
///C++11 makes possible to create Singleton without any warry about thread-safeness
@ -40,19 +64,18 @@ ProfileManager& ProfileManager::instance()
return m_profileManager;
}
void ProfileManager::registerMark(Mark* _mark)
{
if (!m_isEnabled)
return;
}
void ProfileManager::beginBlock(Block* _block)
{
if (!m_isEnabled)
return;
guard_lock_t lock(m_spin);
m_openedBracketsMap[_block->getThreadId()].push(_block);
if (_block->getType() != BLOCK_TYPE_MARK){
guard_lock_t lock(m_spin);
m_openedBracketsMap[_block->getThreadId()].push(_block);
}
else{
_internalInsertBlock(_block);
}
}
void ProfileManager::endBlock()
@ -73,6 +96,7 @@ void ProfileManager::endBlock()
if (lastBlock && !lastBlock->isFinished()){
lastBlock->finish();
}
_internalInsertBlock(lastBlock);
stackOfOpenedBlocks.pop();
}
@ -80,3 +104,9 @@ void ProfileManager::setEnabled(bool isEnable)
{
m_isEnabled = isEnable;
}
void ProfileManager::_internalInsertBlock(profiler::Block* _block)
{
guard_lock_t lock(m_storedSpin);
m_blocks.emplace_back(new SerilizedBlock(_block));
}

View File

@ -25,6 +25,20 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
#include <stack>
#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
{
@ -41,11 +55,16 @@ class ProfileManager
map_of_threads_stacks m_openedBracketsMap;
profiler::spin_lock m_spin;
profiler::spin_lock m_storedSpin;
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:
static ProfileManager& instance();
void registerMark(profiler::Mark* _mark);
~ProfileManager();
void beginBlock(profiler::Block* _block);
void endBlock();
void setEnabled(bool isEnable);