c++ - Quick and dirty way to profile your code -
what method use when want performance data specific code paths?
this method has several limitations, still find useful. i'll list limitations (i know of) front , let whoever wants use @ own risk.
- the original version posted over-reported time spent in recursive calls (as pointed out in comments answer).
- it's not thread safe, wasn't thread safe before added code ignore recursion , it's less thread safe now.
- although it's efficient if it's called many times (millions), have measurable effect on outcome scopes measure take longer don't.
i use class when problem @ hand doesn't justify profiling code or data profiler want verify. sums time spent in specific block , @ end of program outputs debug stream (viewable dbgview), including how many times code executed (and average time spent of course)).
#pragma once #include <tchar.h> #include <windows.h> #include <sstream> #include <boost/noncopyable.hpp> namespace scope_timer { class time_collector : boost::noncopyable { __int64 total; large_integer start; size_t times; const tchar* name; double cpu_frequency() { // cache cpu frequency, doesn't change. static double ret = 0; // store double devision later on floating point , not truncating if (ret == 0) { large_integer freq; queryperformancefrequency(&freq); ret = static_cast<double>(freq.quadpart); } return ret; } bool in_use; public: time_collector(const tchar* n) : times(0) , name(n) , total(0) , start(large_integer()) , in_use(false) { } ~time_collector() { std::basic_ostringstream<tchar> msg; msg << _t("scope_timer> ") << name << _t(" called: "); double seconds = total / cpu_frequency(); double average = seconds / times; msg << times << _t(" times total time: ") << seconds << _t(" seconds ") << _t(" (avg ") << average <<_t(")\n"); outputdebugstring(msg.str().c_str()); } void add_time(__int64 ticks) { total += ticks; ++times; in_use = false; } bool aquire() { if (in_use) return false; in_use = true; return true; } }; class one_time : boost::noncopyable { large_integer start; time_collector* collector; public: one_time(time_collector& tc) { if (tc.aquire()) { collector = &tc; queryperformancecounter(&start); } else collector = 0; } ~one_time() { if (collector) { large_integer end; queryperformancecounter(&end); collector->add_time(end.quadpart - start.quadpart); } } }; } // usage time_this_scope(xx); xx c variable name (can begin number) #define time_this_scope(name) \ static scope_timer::time_collector st_time_collector_##name(_t(#name)); \ scope_timer::one_time st_one_time_##name(st_time_collector_##name)
Comments
Post a Comment