libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_UTILS_BENCHMARK_HPP__ 00029 #define MOOST_UTILS_BENCHMARK_HPP__ 00030 00072 #include <iostream> 00073 #include <string> 00074 #include <vector> 00075 #include <map> 00076 00077 #include <boost/thread.hpp> 00078 #include <boost/date_time/posix_time/posix_time.hpp> 00079 00080 #include "foreach.hpp" 00081 #include "histogram.hpp" 00082 00083 namespace moost { namespace utils { 00084 00085 class benchmark 00086 { 00087 private: 00088 typedef std::map< std::string, std::vector<float> > timings_type; 00089 00090 public: 00091 class timer 00092 { 00093 public: 00094 timer(benchmark& bm, const std::string& default_result = "error") 00095 : m_bm(bm) 00096 , m_default_result(default_result) 00097 { 00098 restart(); 00099 } 00100 00101 ~timer() 00102 { 00103 try 00104 { 00105 stop(m_default_result); 00106 } 00107 catch (...) 00108 { 00109 } 00110 } 00111 00112 void restart() 00113 { 00114 m_running = true; 00115 m_start = boost::posix_time::microsec_clock::universal_time(); 00116 } 00117 00118 void stop(const std::string& result = "success") 00119 { 00120 if (m_running) 00121 { 00122 boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); 00123 float seconds = 1e-6*(now - m_start).total_microseconds(); 00124 m_bm.add_timing(result, seconds); 00125 m_running = false; 00126 } 00127 } 00128 00129 private: 00130 benchmark& m_bm; 00131 bool m_running; 00132 boost::posix_time::ptime m_start; 00133 const std::string m_default_result; 00134 }; 00135 00136 benchmark(const std::string& name, size_t num_threads = 1) 00137 : m_name(name) 00138 , m_num_threads(num_threads) 00139 { 00140 } 00141 00142 void add_timing(const std::string& timing, float time) 00143 { 00144 boost::mutex::scoped_lock lock(m_mutex); 00145 m_timings[timing].push_back(time); 00146 } 00147 00148 void output(std::ostream& os, size_t bins = 120, size_t height = 25, float offset = 0.0f, float hi_cut = 0.02f) const 00149 { 00150 boost::mutex::scoped_lock lock(m_mutex); 00151 00152 moost::utils::histogram<float> cumulative("s"); 00153 cumulative.set_display_range(offset, 1.0f - hi_cut); 00154 00155 os << std::endl << "=== " << m_name << " ===" << std::endl << std::endl; 00156 00157 foreach (const timings_type::value_type& t, m_timings) 00158 { 00159 moost::utils::histogram<float> h("s", bins, height); 00160 h.set_display_range(offset, 1.0f - hi_cut); 00161 00162 h.add(t.second.begin(), t.second.end(), t.first, "*"); 00163 cumulative.add(t.second.begin(), t.second.end(), t.first, t.first.substr(0, 1)); 00164 00165 h.draw(os); 00166 00167 os << std::endl; 00168 } 00169 00170 cumulative.draw(os); 00171 os << std::endl; 00172 00173 os << "requests per second: " << m_num_threads/cumulative.mean() << std::endl; 00174 } 00175 00176 private: 00177 mutable boost::mutex m_mutex; 00178 timings_type m_timings; 00179 const std::string m_name; 00180 const size_t m_num_threads; 00181 }; 00182 00183 }} 00184 00185 #endif