mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 00:31: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);
|
||||
|
||||
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
|
||||
@ -98,6 +104,11 @@ namespace profiler
|
||||
public:
|
||||
Block(const char* _name, color_t _color = 0);
|
||||
~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(){
|
||||
PROFILER_BEGIN_FUNCTION_BLOCK;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
void longTimeFunction(){
|
||||
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_ENABLE;
|
||||
longTimeFunction();
|
||||
shortTimeFunction();
|
||||
|
||||
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_GROUPED("mark1",1);
|
||||
PROFILER_DISABLE;
|
||||
//PROFILER_DISABLE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ set(CPP_FILES
|
||||
set(H_FILES
|
||||
${ROOT}/include/profiler/profiler.h
|
||||
profile_manager.h
|
||||
spin_lock.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -33,12 +33,17 @@ void Mark::tick(timestamp_t& stamp)
|
||||
|
||||
Block::Block(const char* _name, color_t _color) :
|
||||
Mark(_name, _color),
|
||||
end(begin)
|
||||
end(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
tick(end);
|
||||
if (this->isCleared())
|
||||
return;
|
||||
if (!this->isFinished())
|
||||
this->finish();
|
||||
|
||||
endBlock();
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "profile_manager.h"
|
||||
#include "profiler/profiler.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
using namespace profiler;
|
||||
|
||||
extern "C"{
|
||||
@ -39,19 +41,41 @@ ProfileManager& ProfileManager::instance()
|
||||
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()
|
||||
{
|
||||
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)
|
||||
|
@ -21,6 +21,11 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "profiler/profiler.h"
|
||||
|
||||
#include "spin_lock.h"
|
||||
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
class ProfileManager
|
||||
{
|
||||
ProfileManager();
|
||||
@ -29,6 +34,14 @@ class ProfileManager
|
||||
static ProfileManager m_profileManager;
|
||||
|
||||
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:
|
||||
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