0
0
mirror of https://github.com/yse/easy_profiler.git synced 2025-01-16 12:12:45 +08:00
easy_profiler/src/profile_manager.cpp

191 lines
4.6 KiB
C++
Raw Normal View History

2016-02-16 23:21:12 +03:00
#include "profile_manager.h"
2016-02-18 19:27:17 +03:00
#include <thread>
2016-02-20 19:21:14 +03:00
#include <string.h>
2016-02-24 00:08:13 +03:00
#include <fstream>
2016-02-16 23:21:12 +03:00
using namespace profiler;
auto& MANAGER = ProfileManager::instance();
2016-02-16 23:21:12 +03:00
extern "C"{
void PROFILER_API endBlock()
{
MANAGER.endBlock();
}
2016-02-18 00:45:13 +03:00
void PROFILER_API setEnabled(bool isEnable)
{
MANAGER.setEnabled(isEnable);
}
void PROFILER_API beginBlock(Block& _block)
2016-02-18 00:45:13 +03:00
{
MANAGER.beginBlock(_block);
2016-02-18 00:45:13 +03:00
}
2016-07-04 22:53:02 +03:00
unsigned int PROFILER_API dumpBlocksToFile(const char* filename)
{
return MANAGER.dumpBlocksToFile(filename);
2016-07-04 22:53:02 +03:00
}
2016-07-31 22:12:11 +03:00
void PROFILER_API setThreadName(const char* name)
{
return MANAGER.setThreadName(name);
2016-07-31 22:12:11 +03:00
}
2016-02-16 23:21:12 +03:00
}
SerializedBlock* SerializedBlock::create(const Block& block, uint64_t& memory_size)
2016-06-17 16:31:09 +03:00
{
auto name_length = static_cast<uint16_t>(strlen(block.getName()));
auto size = static_cast<uint16_t>(sizeof(BaseBlockData) + name_length + 1);
auto data = ::new char[size];
::new (static_cast<void*>(data)) SerializedBlock(block, name_length);
memory_size += size;
return reinterpret_cast<SerializedBlock*>(data);
2016-06-17 16:31:09 +03:00
}
void SerializedBlock::destroy(SerializedBlock* that)
2016-02-24 06:31:05 +03:00
{
::delete[] reinterpret_cast<char*>(that);
2016-02-24 06:31:05 +03:00
}
SerializedBlock::SerializedBlock(const Block& block, uint16_t name_length)
: BaseBlockData(block)
2016-02-24 06:31:05 +03:00
{
auto name = const_cast<char*>(getName());
strncpy(name, block.getName(), name_length);
name[name_length] = 0;
2016-02-24 06:31:05 +03:00
}
2016-02-16 23:21:12 +03:00
//////////////////////////////////////////////////////////////////////////
BlockSourceInfo::BlockSourceInfo(const char* _filename, int _linenumber) : m_id(MANAGER.addSource(_filename, _linenumber))
{
}
SourceBlock::SourceBlock(const char* _filename, int _line) : m_filename(_filename), m_line(_line)
{
}
//////////////////////////////////////////////////////////////////////////
2016-02-16 23:21:12 +03:00
ProfileManager::ProfileManager()
{
}
ProfileManager::~ProfileManager()
{
2016-07-04 22:53:02 +03:00
//dumpBlocksToFile("test.prof");
}
ProfileManager& ProfileManager::instance()
2016-02-16 23:21:12 +03:00
{
///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;
2016-02-16 23:21:12 +03:00
}
void ProfileManager::beginBlock(Block& _block)
2016-02-18 00:45:13 +03:00
{
if (!m_isEnabled)
2016-02-18 19:27:17 +03:00
return;
if (BLOCK_TYPE_BLOCK == _block.getType()){
guard_lock_t lock(m_spin);
m_openedBracketsMap[_block.getThreadId()].emplace(_block);
}
else{
_internalInsertBlock(_block);
}
2016-02-18 00:45:13 +03:00
}
2016-02-16 23:21:12 +03:00
void ProfileManager::endBlock()
{
2016-02-24 00:08:13 +03:00
2016-02-18 19:27:17 +03:00
if (!m_isEnabled)
return;
2016-06-20 23:21:54 +03:00
uint32_t threadId = getCurrentThreadId();
2016-06-20 23:10:14 +03:00
2016-02-18 19:27:17 +03:00
guard_lock_t lock(m_spin);
auto& stackOfOpenedBlocks = m_openedBracketsMap[threadId];
if (stackOfOpenedBlocks.empty())
return;
Block& lastBlock = stackOfOpenedBlocks.top();
if(!lastBlock.isFinished())
lastBlock.finish();
_internalInsertBlock(lastBlock);
2016-02-18 19:27:17 +03:00
stackOfOpenedBlocks.pop();
2016-02-16 23:21:12 +03:00
}
void ProfileManager::setEnabled(bool isEnable)
{
m_isEnabled = isEnable;
2016-02-16 23:25:12 +03:00
}
void ProfileManager::_internalInsertBlock(const profiler::Block& _block)
{
guard_lock_t lock(m_storedSpin);
m_blocks.emplace_back(SerializedBlock::create(_block, m_blocksMemorySize));
2016-02-20 19:21:14 +03:00
}
2016-07-04 22:53:02 +03:00
unsigned int ProfileManager::dumpBlocksToFile(const char* filename)
{
::std::ofstream of(filename, std::fstream::binary);
2016-07-04 22:53:02 +03:00
auto blocks_number = static_cast<uint32_t>(m_blocks.size());
//of.write((const char*)&blocks_number, sizeof(uint32_t));
of.write((const char*)&m_blocksMemorySize, sizeof(uint64_t));
for (auto b : m_blocks)
{
auto sz = static_cast<uint16_t>(sizeof(BaseBlockData) + strlen(b->getName()) + 1);
of.write((const char*)&sz, sizeof(uint16_t));
of.write(b->data(), sz);
SerializedBlock::destroy(b);
}
2016-07-04 22:53:02 +03:00
m_blocksMemorySize = 0;
m_blocks.clear();
2016-07-04 22:53:02 +03:00
return blocks_number;
2016-07-04 22:53:02 +03:00
}
2016-07-31 22:12:11 +03:00
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;
2016-07-31 22:12:11 +03:00
profiler::Block block(name, current_thread_id, 0, profiler::BLOCK_TYPE_THREAD_SIGN);
m_blocks.emplace_back(SerializedBlock::create(block, m_blocksMemorySize));
m_namedThreades.insert(current_thread_id);
2016-07-31 22:12:11 +03:00
}
//////////////////////////////////////////////////////////////////////////
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;
}
//////////////////////////////////////////////////////////////////////////