|
#ifndef PROFILER |
|
#define PROFILER |
|
|
|
#include <map> |
|
#include <string> |
|
#include <utility> |
|
#include <fstream> |
|
#include <iomanip> |
|
|
|
#include <osg/Timer> |
|
#include <osg/Notify> |
|
|
|
|
|
class Profiler |
|
{ |
|
public: |
|
typedef std::pair<unsigned int, double> ProfileStat; |
|
typedef std::map< std::string, ProfileStat> ProfileMap; |
|
typedef std::pair<std::string, ProfileStat> ProfileItem; |
|
static ProfileMap _profile; |
|
|
|
enum SortFilter { |
|
by_name=1, |
|
by_calls=2, |
|
by_seconds=4 |
|
}; |
|
|
|
struct profile_item_sort |
|
{ |
|
profile_item_sort(SortFilter filter): _filter(filter) |
|
{} |
|
|
|
inline bool operator() (const ProfileItem& item1, const ProfileItem& item2) |
|
{ |
|
if(_filter & by_name) { |
|
return (item1.first < item2.first); |
|
} |
|
else if(_filter & by_calls) { |
|
return (item1.second.first > item2.second.first); |
|
} |
|
|
|
return (item1.second.second > item2.second.second); |
|
} |
|
|
|
SortFilter _filter; |
|
}; |
|
|
|
static void dump(SortFilter filter=by_seconds) { |
|
std::ofstream out("/tmp/profile"); |
|
std::vector<ProfileItem> data(Profiler::_profile.begin(), Profiler::_profile.end()); |
|
|
|
if(filter) { |
|
std::sort(data.begin(), data.end(), profile_item_sort(filter)); |
|
} |
|
|
|
out << std::setw(30) << "label" << " " << std::setw(10) << "#calls" << " " << "seconds" << std::endl; |
|
for(std::vector<ProfileItem>::const_iterator item = data.begin() ; item != data.end() ; ++ item) { |
|
out << std::setw(30) << item->first << " " |
|
<< std::setw(10) << item->second.first << " " |
|
<< std::setprecision(6) << item->second.second << std::endl; |
|
} |
|
} |
|
|
|
Profiler(const std::string& label): _start(getTick()), _label(label) |
|
{} |
|
|
|
~Profiler() { |
|
_stop = getTick(); |
|
double seconds = getElapsedSeconds(); |
|
|
|
std::map< std::string, std::pair<unsigned int, double> >::iterator func = Profiler::_profile.find(_label); |
|
if(Profiler::_profile.find(_label) == Profiler::_profile.end()) { |
|
_profile.insert(ProfileItem(_label, std::pair<unsigned int, double>(1, seconds))); |
|
} |
|
else { |
|
func->second.first += 1; |
|
func->second.second += seconds; |
|
} |
|
} |
|
|
|
protected: |
|
osg::Timer_t _start, _stop; |
|
std::string _label; |
|
|
|
inline osg::Timer_t getTick() const { |
|
return osg::Timer::instance()->tick(); |
|
} |
|
|
|
inline double getElapsedSeconds() const { |
|
return osg::Timer::instance()->delta_s(_start, _stop); |
|
} |
|
}; |
|
|
|
#endif |