Skip to content

Instantly share code, notes, and snippets.

@marchelbling
Last active April 11, 2017 07:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marchelbling/342875b9f835e75909ad to your computer and use it in GitHub Desktop.
Save marchelbling/342875b9f835e75909ad to your computer and use it in GitHub Desktop.
Simple (intrusive) OSG profiler

Requires:

  • to define Profiler::ProfileMap Profiler::_profile; somewhere
  • to scope blocks of code with { Profiler p("block label"); ... }; do not use an anonymous variable otherwise the timer will be wrong as anonymous object will be deleted at the end of the instruction (see http://stackoverflow.com/a/2298796/626278)
  • to call Profiler::dump() to dump profiling stats in /tmp/profile
#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment