mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 08:41:02 +08:00
Added logic of push/pop blocks
This commit is contained in:
parent
561f79e8e6
commit
dbe5af1125
@ -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); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
68
src/spin_lock.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user