Advertisement
Guest User

Untitled

a guest
Nov 21st, 2014
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.36 KB | None | 0 0
  1. #pragma once
  2. #include <util/string.hpp>
  3. #include <util/time.hpp>
  4. #include <util/thread.hpp>
  5. #include <util/json.hpp>
  6.  
  7. #include <mutex>
  8. #include <array>
  9. #include <map>
  10. #include <atomic>
  11. #include "logger.hpp"
  12.  
  13.  
  14. namespace Labs {
  15. #define EVENT_DECL(identificator_user, event_var, event_name) static ::Labs::Identificator<identificator_user> event_var = ::Labs::Identificator<identificator_user>::init_event(event_name);
  16. #define TIMER_SECTION_DECL(event_name) EVENT_DECL(ThreadTimer, event_name, #event_name)
  17. #define THREAD_TIMER_SECTION(event_name) TIMER_SECTION_DECL(event_name) ThreadTimer::set_section(event_name)
  18. #define THREAD_TIMER_SECTION_END ThreadTimer::end_section()
  19. #define THREAD_TIMER_SECTION_AUTO(event_name) TIMER_SECTION_DECL(event_name) auto holder = ThreadTimer::set_auto_section(event_name)
  20.  
  21.     struct ProfItem {
  22.         double total_time;
  23.         unsigned int count;
  24.         double get_avg() const {
  25.             return total_time/count;
  26.         }
  27.         ProfItem& operator+=(const ProfItem& other) {
  28.             total_time += other.total_time;
  29.             count+=other.count;
  30.             return *this;
  31.         }
  32.     };
  33.     constexpr size_t MAX_ID_CNT = 100;
  34.     template<class User>
  35.     class Identificator {
  36.     public:
  37.         static Identificator init_event(const String& name) {
  38.             std::unique_lock<std::mutex> g(init_mutex);
  39.             auto& idx = event_indexes[name];
  40.             if(idx == 0) {
  41.                 idx = ++counter;
  42.                 if(idx >= MAX_ID_CNT) {
  43.                     throw std::runtime_error("Exceeded maximum id count");
  44.                 }
  45.                 names[idx] = name;
  46.                 if(names[0].empty()) {
  47.                     names[0] = "Undefined";
  48.                 }
  49.             }
  50.             g.unlock();
  51.             return Identificator(idx);
  52.         }
  53.  
  54.         Identificator(int _index) :
  55.                 index(_index)
  56.         {
  57.         }
  58.  
  59.         Identificator() :
  60.                 index()
  61.         {}
  62.  
  63.         Identificator(const Identificator& other) = default;
  64.  
  65.         Identificator& operator=(const Identificator& other) = default;
  66.  
  67.         int get_int() const {
  68.             return index;
  69.         }
  70.  
  71.         const String& get_label() const {
  72.             return names[index];
  73.         }
  74.  
  75.         bool is_registered() const {
  76.             return !names[index].empty();
  77.         }
  78.  
  79.         bool operator<(const Identificator& other) const{
  80.             return index < other.index;
  81.         }
  82.  
  83.     private:
  84.         static std::mutex init_mutex;
  85.         static std::map<String,int> event_indexes;
  86.         static std::atomic_int counter;
  87.         static std::array<String, MAX_ID_CNT> names;
  88.         int index;
  89.     };
  90.  
  91.     template<class User>
  92.     std::mutex Identificator<User>::init_mutex;
  93.  
  94.     template<class User>
  95.     std::map<String,int> Identificator<User>::event_indexes;
  96.  
  97.     template<class User>
  98.     std::atomic_int Identificator<User>::counter;
  99.  
  100.     template<class User>
  101.     std::array<String, MAX_ID_CNT> Identificator<User>::names;
  102.  
  103.     class ThreadTimer;
  104.     typedef Identificator<ThreadTimer> TTI;
  105.  
  106.     class ThreadTimer {
  107.     public:
  108.         class SectionEnder {
  109.         public:
  110.             SectionEnder() :
  111.                     owner(true)
  112.             {}
  113.  
  114.             ~SectionEnder() {
  115.                 if(owner) {
  116.                     ThreadTimer::end_section();
  117.                 }
  118.             }
  119.             SectionEnder(const SectionEnder& other) = delete;
  120.             SectionEnder& operator=(const SectionEnder& other) = delete;
  121.             SectionEnder(SectionEnder&& other) :
  122.                     owner(true)
  123.             {
  124.                 other.owner = false;
  125.             }
  126.  
  127.             SectionEnder& operator=(SectionEnder&& other) {
  128.                 owner = true;
  129.                 other.owner = false;
  130.                 return *this;
  131.             }
  132.  
  133.         private:
  134.             bool owner;
  135.         };
  136.         typedef std::function<void(const TTI& id, const ProfItem& val)> ConsumerFun;
  137.  
  138.         static void set_section(const TTI& id) {
  139.             std::cerr << "SECTION " << id.get_label() << std::endl;
  140.             double time = microtime();
  141.             double& s_time = start_time.get();
  142.             if(s_time == 0.0) {
  143.                 s_time = time;
  144.             }
  145.             ProfItem diff {time - s_time, 1};
  146.             TTI& cs = current_section.get();
  147.             timings.get()[cs.get_int()] += diff;
  148.             s_time = time;
  149.             for(size_t i = 0; i < consumers.size(); i++) {
  150.                 consumers[i](cs, diff);
  151.             }
  152.             cs = id;
  153.         }
  154.  
  155.         static SectionEnder set_auto_section(const TTI& id) {
  156.             set_section(id);
  157.             return SectionEnder();
  158.         }
  159.  
  160.         static void end_section() {
  161.             EVENT_DECL(ThreadTimer, event, "Undefined");
  162.             set_section(event);
  163.         }
  164.  
  165.         static void reset() {
  166.             auto& vec = timings.get();
  167.             ProfItem empty {0.0,0};
  168.             std::fill(vec.begin(), vec.end(), empty);
  169.         }
  170.  
  171.     private:
  172.         template<size_t p>
  173.         friend class PeriodicAvgTimer;
  174.         friend class AvgTimer;
  175.         static void register_consumer_fun(const ConsumerFun& fun) {
  176.             consumers.push_back(fun);
  177.         }
  178.         static ThreadLocal<TTI> current_section;
  179.         static ThreadLocal<double> start_time;
  180.         static ThreadLocal<std::array<ProfItem, MAX_ID_CNT>> timings;
  181.         static std::vector<ConsumerFun> consumers;
  182.     };
  183.  
  184.     inline Json::Value timings_to_json(const std::array<ProfItem, MAX_ID_CNT>& data) {
  185.         Json::Value ret;
  186.         for(int i = 0; i < data.size(); i++) {
  187.             if(data[i].count != 0) {
  188.                 TTI id(i);
  189.                 ret[id.get_label()]["all"] = data[i].total_time;
  190.                 ret[id.get_label()]["cnt"] = data[i].count;
  191.                 ret[id.get_label()]["avg"] = data[i].get_avg();
  192.             }
  193.         }
  194.         return ret;
  195.     }
  196.  
  197.     template <size_t period>
  198.     class PeriodicAvgTimer {
  199.     public:
  200.         static Json::Value report_json() {
  201.             log_info("AVG:", period, timings_to_json(timings), last_flush, registrator);
  202.             return timings_to_json(old_timings);
  203.         }
  204.  
  205.     private:
  206.         static void add_val(const TTI& id, ProfItem val) {
  207.             std::cerr << "ADD: " << id.get_label() << " : " << period << std::endl;
  208.             double c_time = microtime();
  209.             if(c_time - last_flush > period) {
  210.                 static std::mutex m;
  211.                 std::lock_guard<std::mutex> g(m);
  212.                 if(c_time - last_flush > period) {
  213.                     timings.swap(old_timings);
  214.                     ProfItem it{0.0, 0};
  215.                     std::fill(timings.begin(), timings.end(), it);
  216.                     last_flush = c_time;
  217.                 }
  218.             }
  219.             timings[id.get_int()] += val;
  220.         }
  221.  
  222.  
  223.         static int register_for_updates() {
  224.             std::cerr << "REG:" << period << std::endl;
  225.             ThreadTimer::register_consumer_fun(PeriodicAvgTimer::add_val);
  226.             //it's a place holder
  227.             return 42;
  228.         }
  229.         static std::array<ProfItem, MAX_ID_CNT> timings;
  230.         static std::array<ProfItem, MAX_ID_CNT> old_timings;
  231.         static int registrator;
  232.         static double last_flush;
  233.     };
  234.  
  235.     template<size_t period>
  236.     std::array<ProfItem, MAX_ID_CNT> PeriodicAvgTimer<period>::timings;
  237.  
  238.     template<size_t period>
  239.     std::array<ProfItem, MAX_ID_CNT> PeriodicAvgTimer<period>::old_timings;
  240.  
  241.     template<size_t period>
  242.     int  PeriodicAvgTimer<period>::registrator = PeriodicAvgTimer<period>::register_for_updates();
  243.  
  244.     template<size_t period>
  245.     double PeriodicAvgTimer<period>::last_flush = 0.0;
  246.  
  247.     class AvgTimer {
  248.     public:
  249.         static Json::Value report_json() {
  250.             return timings_to_json(timings);
  251.         }
  252.  
  253.     private:
  254.         static void add_val(const Identificator<ThreadTimer>& id, ProfItem val) {
  255.             timings[id.get_int()] += val;
  256.         }
  257.  
  258.         static int registrator;
  259.         static int register_for_updates() {
  260.             std::cerr << "REG AVG:" << std::endl;
  261.             ThreadTimer::register_consumer_fun(AvgTimer::add_val);
  262.             //it's a place holder
  263.             return 42;
  264.         }
  265.         static std::array<ProfItem, MAX_ID_CNT> timings;
  266.     };
  267. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement