libmoost
/home/mhx/git/github/libmoost/include/moost/utils/benchmark.hpp
Go to the documentation of this file.
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