在很多时候,程序百分之八十的效率浪费到百分之二十的代码中,在优化效率的时候,针对这些瓶颈函数的改良就显得至关重要。这里提供了一个简单的工具,用于跟踪函数的调用次序和时间花费,并打印出结果提供参考。
OgreDebugTrace.h
- #ifndef OgreDebugTrace_H_
- #define OgreDebugTrace_H_
- #ifdef _DEBUG
- #define OGRE_DEBUG_TRACE DebugTrace ____(__FILE__, __LINE__, __FUNCTION__);
- #else
- #define OGRE_DEBUG_TRACE
- #endif
- #include <Ogre.h>
- namespace Ogre
- {
- class DebugTraceManager: public Ogre::Singleton<DebugTraceManager>
- {
- typedef HashMap<Ogre::String, unsigned long> LogMsgMap;
- public:
- DebugTraceManager(Ogre::Log * log);
- ~DebugTraceManager(void);
- void print(const char * file, long line, const char * function, size_t layer);
- void log(const Ogre::String & name,size_t time, size_t layer);
- void printAll();
- unsigned long getTime();
- private:
- Ogre::Timer _timer;
- LogMsgMap _logMsg;
- Ogre::Log * _log;
- unsigned long _time;
- };
- class DebugTrace
- {
- public:
- DebugTrace(const char * file, long line, const char * function);
- ~DebugTrace();
- private:
- static size_t layer;
- unsigned long _time;
- Ogre::String _name;
- };
- }
- #endif
OgreDebugTrace.cpp
- #include "OgreDebugTrace.h"
- namespace Ogre
- {
- template<> DebugTraceManager* Singleton<DebugTraceManager>::ms_Singleton = 0;
- size_t DebugTrace::layer = 0;
- DebugTraceManager::DebugTraceManager(Ogre::Log * log):_log(log)
- {
- _time = getTime();
- }
- DebugTraceManager::~DebugTraceManager(void)
- {
- printAll();
- }
- void DebugTraceManager::print(const char * file, long line, const char * function, size_t layer)
- {
- std::stringstream ss;
- while(layer--)
- {
- ss<<" ";
- }
- ss<<"Trace begin"<<function<<", in "<<file<<" line:"<<line<<".";
- _log->logMessage(ss.str());
- }
- void DebugTraceManager::log(const Ogre::String & name,size_t time, size_t layer)
- {
- std::stringstream ss;
- while(layer--)
- {
- ss<<" ";
- }
- ss<<"Trace over, cost:"<<time;
- _log->logMessage(ss.str());
- LogMsgMap::iterator it = _logMsg.find(name);
- if(it == _logMsg.end())
- {
- _logMsg.insert(std::make_pair(name, time));
- }
- else
- {
- it->second += time;
- }
- }
- void DebugTraceManager::printAll()
- {
- LogMsgMap::iterator it;
- _time = getTime()-_time;
- std::stringstream ss;
- ss<<"in total cost:"<<_time<<std::endl;
- for(it = _logMsg.begin(); it != _logMsg.end(); ++it)
- {
- ss<<it->first<<"Cost:"<<it->second
- <<"("<<(float(it->second)/float(_time) *100.0f)<<"%)."
- <<std::endl;
- }
- _log->logMessage(ss.str());
- }
- unsigned long DebugTraceManager::getTime()
- {
- return _timer.getMicroseconds();
- }
- DebugTrace::DebugTrace(const char * file, long line, const char * function):_name(function)
- {
- DebugTraceManager::getSingleton().print(file, line, function, layer);
- _time = DebugTraceManager::getSingleton().getTime();
- ++layer;
- }
- DebugTrace::~DebugTrace()
- {
- _time = DebugTraceManager::getSingleton().getTime() - _time;
- --layer;
- DebugTraceManager::getSingleton().log(_name, _time, layer);
- }
- }
在初始化Ogre之后加入下面的代码,开始跟踪调试:
#ifdef _DEBUG _log = Ogre::LogManager::getSingleton().createLog("trace.log"); _traceManager = new DebugTraceManager(_log); #endif
在每个要跟踪的函数开始的地方加入宏:
OGRE_DEBUG_TRACE
在程序最后,通过下面的代码清理:
#ifdef _DEGUG if(_traceManager) delete _traceManager; Ogre::LogManager::getSingleton().destroyLog(_log); #endif
局限:因为上面提供的代码是基于Ogre日志管理而实现的,所以只能在构建Ogre之后进行跟踪记录,但是可以很容易根据需要通过std::stream来代替Ogre::Log来实现相同功能的模块,这样就可以跟踪Ogre之外的代码了。