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