0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-29 10:05:48 +08:00
easy_profiler/src/profile_manager.cpp

208 lines
4.6 KiB
C++

#include "profile_manager.h"
#include <thread>
#include <string.h>
#include <fstream>
using namespace profiler;
extern "C"{
void PROFILER_API endBlock()
{
ProfileManager::instance().endBlock();
}
void PROFILER_API setEnabled(bool isEnable)
{
ProfileManager::instance().setEnabled(isEnable);
}
void PROFILER_API beginBlock(Block* _block)
{
ProfileManager::instance().beginBlock(_block);
}
unsigned int PROFILER_API dumpBlocksToFile(const char* filename)
{
return ProfileManager::instance().dumpBlocksToFile(filename);
}
void PROFILER_API setThreadName(const char* name)
{
return ProfileManager::instance().setThreadName(name);
}
}
SerializedBlock::SerializedBlock(const Block* block)
: m_size(sizeof(BaseBlockData))
, m_data(nullptr)
{
uint16_t name_len = static_cast<uint16_t>(strlen(block->getName()) + 1);
m_size += name_len;
m_data = new char[m_size];
memcpy(m_data, block, sizeof(BaseBlockData));
strncpy(m_data + sizeof(BaseBlockData), block->getName(), name_len);
}
SerializedBlock::SerializedBlock(uint16_t _size, char* _data)
: m_size(_size)
, m_data(_data)
{
}
SerializedBlock::~SerializedBlock()
{
if (m_data != nullptr)
delete[] m_data;
}
SerializedBlock::SerializedBlock(const SerializedBlock& other)
: m_size(other.m_size)
, m_data(new char[other.m_size])
{
memcpy(m_data, other.m_data, m_size);
}
SerializedBlock::SerializedBlock(SerializedBlock&& that)
: m_size(that.m_size)
, m_data(that.m_data)
{
that.m_size = 0;
that.m_data = nullptr;
}
const BaseBlockData * SerializedBlock::block() const
{
return reinterpret_cast<const BaseBlockData*>(m_data);
}
const char* SerializedBlock::getBlockName() const
{
return m_data + sizeof(BaseBlockData);
}
//////////////////////////////////////////////////////////////////////////
BlockSourceInfo::BlockSourceInfo(const char* _filename, int _linenumber) : m_id(ProfileManager::instance().addSource(_filename, _linenumber))
{
}
SourceBlock::SourceBlock(const char* _filename, int _line) : m_filename(_filename), m_line(_line)
{
}
//////////////////////////////////////////////////////////////////////////
ProfileManager::ProfileManager()
{
}
ProfileManager::~ProfileManager()
{
//dumpBlocksToFile("test.prof");
}
ProfileManager& ProfileManager::instance()
{
///C++11 makes possible to create Singleton without any warry about thread-safeness
///http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
static ProfileManager m_profileManager;
return m_profileManager;
}
void ProfileManager::beginBlock(Block* _block)
{
if (!m_isEnabled)
return;
if (BLOCK_TYPE_BLOCK == _block->getType()){
guard_lock_t lock(m_spin);
m_openedBracketsMap[_block->getThreadId()].push(_block);
}
else{
_internalInsertBlock(_block);
}
}
void ProfileManager::endBlock()
{
if (!m_isEnabled)
return;
uint32_t threadId = getCurrentThreadId();
guard_lock_t lock(m_spin);
auto& stackOfOpenedBlocks = m_openedBracketsMap[threadId];
if (stackOfOpenedBlocks.empty())
return;
Block* lastBlock = stackOfOpenedBlocks.top();
if (lastBlock && !lastBlock->isFinished()){
lastBlock->finish();
}
_internalInsertBlock(lastBlock);
stackOfOpenedBlocks.pop();
}
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 SerializedBlock(_block));
}
unsigned int ProfileManager::dumpBlocksToFile(const char* filename)
{
std::ofstream of(filename, std::fstream::binary);
for (auto* b : m_blocks){
uint16_t sz = b->size();
of.write((const char*)&sz, sizeof(uint16_t));
of.write(b->data(), b->size());
delete b;
}
unsigned int size = (unsigned int)m_blocks.size();
m_blocks.clear();
return size;
}
void ProfileManager::setThreadName(const char* name)
{
auto current_thread_id = getCurrentThreadId();
guard_lock_t lock(m_storedSpin);
auto find_it = m_namedThreades.find(current_thread_id);
if (find_it != m_namedThreades.end())
return;
profiler::Block block(name, current_thread_id, 0, profiler::BLOCK_TYPE_THREAD_SIGN);
m_blocks.emplace_back(new SerializedBlock(&block));
m_namedThreades.insert(current_thread_id);
}
//////////////////////////////////////////////////////////////////////////
unsigned int ProfileManager::addSource(const char* _filename, int _line)
{
guard_lock_t lock(m_storedSpin);
const auto id = static_cast<unsigned int>(m_sources.size());
m_sources.emplace_back(_filename, _line);
return id;
}
//////////////////////////////////////////////////////////////////////////