0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 00:21:11 +08:00

Added logic of push/pop blocks

This commit is contained in:
Sergey Yagovtsev 2016-02-18 19:27:17 +03:00
parent 561f79e8e6
commit dbe5af1125
7 changed files with 139 additions and 8 deletions

View File

@ -90,6 +90,12 @@ namespace profiler
Mark(const char* _name, color_t _color = 0); Mark(const char* _name, color_t _color = 0);
inline unsigned char getType() const { return type; }
inline color_t getColor() const { return color; }
inline timestamp_t getBegin() const { return begin; }
inline size_t getThreadId() const { return thread_id; }
inline const char* getName() const { return name; }
}; };
class PROFILER_API Block : public Mark class PROFILER_API Block : public Mark
@ -98,6 +104,11 @@ namespace profiler
public: public:
Block(const char* _name, color_t _color = 0); Block(const char* _name, color_t _color = 0);
~Block(); ~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); }
}; };
} }

View File

@ -4,12 +4,12 @@
void shortTimeFunction(){ void shortTimeFunction(){
PROFILER_BEGIN_FUNCTION_BLOCK; PROFILER_BEGIN_FUNCTION_BLOCK;
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
void longTimeFunction(){ void longTimeFunction(){
PROFILER_BEGIN_FUNCTION_BLOCK; PROFILER_BEGIN_FUNCTION_BLOCK;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
} }
@ -21,10 +21,19 @@ int main()
//profiler::registerMark(&bl); //profiler::registerMark(&bl);
PROFILER_ENABLE; PROFILER_ENABLE;
longTimeFunction();
shortTimeFunction();
PROFILER_BEGIN_BLOCK("block1"); PROFILER_BEGIN_BLOCK("block1");
PROFILER_BEGIN_BLOCK("block2");
PROFILER_BEGIN_BLOCK("block3");
PROFILER_BEGIN_BLOCK("block4");
PROFILER_END_BLOCK;
//PROFILER_END_BLOCK;
PROFILER_ADD_MARK("mark1"); PROFILER_ADD_MARK("mark1");
PROFILER_ADD_MARK_GROUPED("mark1",1); PROFILER_ADD_MARK_GROUPED("mark1",1);
PROFILER_DISABLE; //PROFILER_DISABLE;
return 0; return 0;
} }

View File

@ -8,6 +8,7 @@ set(CPP_FILES
set(H_FILES set(H_FILES
${ROOT}/include/profiler/profiler.h ${ROOT}/include/profiler/profiler.h
profile_manager.h profile_manager.h
spin_lock.h
) )
set(SOURCES set(SOURCES

View File

@ -33,12 +33,17 @@ void Mark::tick(timestamp_t& stamp)
Block::Block(const char* _name, color_t _color) : Block::Block(const char* _name, color_t _color) :
Mark(_name, _color), Mark(_name, _color),
end(begin) end(0)
{ {
} }
Block::~Block() Block::~Block()
{ {
tick(end); if (this->isCleared())
return;
if (!this->isFinished())
this->finish();
endBlock();
} }

View File

@ -1,6 +1,8 @@
#include "profile_manager.h" #include "profile_manager.h"
#include "profiler/profiler.h" #include "profiler/profiler.h"
#include <thread>
using namespace profiler; using namespace profiler;
extern "C"{ extern "C"{
@ -39,19 +41,41 @@ ProfileManager& ProfileManager::instance()
return m_profileManager; return m_profileManager;
} }
void ProfileManager::registerMark(profiler::Mark* _mark) void ProfileManager::registerMark(Mark* _mark)
{ {
if (!m_isEnabled)
return;
} }
void ProfileManager::beginBlock(profiler::Block* _block) void ProfileManager::beginBlock(Block* _block)
{ {
if (!m_isEnabled)
return;
guard_lock_t lock(m_spin);
m_openedBracketsMap[_block->getThreadId()].push(_block);
} }
void ProfileManager::endBlock() void ProfileManager::endBlock()
{ {
if (!m_isEnabled)
return;
size_t threadId = std::hash<std::thread::id>()(std::this_thread::get_id());
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();
}
stackOfOpenedBlocks.pop();
} }
void ProfileManager::setEnabled(bool isEnable) void ProfileManager::setEnabled(bool isEnable)

View File

@ -21,6 +21,11 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
#include "profiler/profiler.h" #include "profiler/profiler.h"
#include "spin_lock.h"
#include <stack>
#include <map>
class ProfileManager class ProfileManager
{ {
ProfileManager(); ProfileManager();
@ -29,6 +34,14 @@ class ProfileManager
static ProfileManager m_profileManager; static ProfileManager m_profileManager;
bool m_isEnabled = false; bool m_isEnabled = false;
typedef std::stack<profiler::Block*> stack_of_blocks_t;
typedef std::map<size_t, stack_of_blocks_t> map_of_threads_stacks;
map_of_threads_stacks m_openedBracketsMap;
profiler::spin_lock m_spin;
typedef profiler::guard_lock<profiler::spin_lock> guard_lock_t;
public: public:
static ProfileManager& instance(); static ProfileManager& instance();

68
src/spin_lock.h Normal file
View File

@ -0,0 +1,68 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016 Sergey Yagovtsev
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef ________SPIN_LOCK__________H______
#define ________SPIN_LOCK__________H______
#include <atomic>
namespace profiler{
class spin_lock
{
std::atomic_flag m_lock;
public:
void lock()
{
while (m_lock.test_and_set(std::memory_order_acquire)){}
}
void unlock()
{
m_lock.clear(std::memory_order_release);
}
spin_lock(){
m_lock.clear();
}
};
template<class T>
class guard_lock
{
T& m_mutex;
bool m_isLocked = false;
public:
guard_lock(T& m) :m_mutex(m){
m_mutex.lock();
m_isLocked = true;
}
~guard_lock(){
this->release();
}
inline void release(){
if (m_isLocked){
m_mutex.unlock();
m_isLocked = false;
}
}
};
}
#endif