Virtual Testbed
Ship dynamics simulator for extreme conditions
profile.hh
1 #ifndef VTESTBED_PROFILE_PROFILE_HH
2 #define VTESTBED_PROFILE_PROFILE_HH
3 
4 #include <vtestbed/config/profile.hh>
5 
6 #if defined(VTB_WITH_PROFILE)
7 
8 #include <chrono>
9 #include <fstream>
10 #include <iosfwd>
11 #include <mutex>
12 #include <ostream>
13 #include <tuple>
14 
15 namespace vtb {
16 
18  namespace profile {
19 
20  extern thread_local int profile_level;
21  extern std::ofstream stream;
22  extern const char* filename;
23  extern std::mutex mtx;
24 
25  template <class Tuple, std::size_t N>
26  struct tuple_traits {
27  static void print(std::ostream& out, const Tuple& t) {
29  out << ' ' << std::get<N-1>(t);
30  }
31  };
32 
33  template <class Tuple>
34  struct tuple_traits<Tuple,1> {
35  static void print(std::ostream& out, const Tuple& t) { out << std::get<0>(t); }
36  };
37 
38 
51  class Profile {
52 
53  private:
55  using time_point = clock::time_point;
56  using duration = clock::duration;
57 
58  private:
59  const char* _tag = "";
60  time_point _t0{duration::zero()};
61  time_point _t1{duration::zero()};
62  int _level{0};
63 
64  public:
65 
66  Profile() = default;
67 
68  inline explicit
69  Profile(const char* tag):
70  _tag{tag},
71  _t0{clock::now()},
72  _t1{duration::zero()},
73  _level{++profile_level}
74  {}
75 
76  ~Profile();
77 
78  void
79  print();
80 
81  };
82 
83  template <class ... Args>
84  class Benchmark {
85 
86  private:
88  using time_point = clock::time_point;
89  using duration = clock::duration;
90  using tuple_type = std::tuple<Args...>;
92 
93  private:
94  const char* _tag = "";
95  time_point _t0{duration::zero()};
96  time_point _t1{duration::zero()};
97  tuple_type _params;
98 
99  public:
100 
101  Benchmark() = default;
102 
103  inline explicit Benchmark(const char* tag, Args... params):
104  _tag{tag}, _t0{clock::now()}, _t1{duration::zero()}, _params{params...} {}
105 
106  inline ~Benchmark() {
107  using namespace std::chrono;
108  this->_t1 = clock::now();
109  auto dt = duration_cast<microseconds>(this->_t1 - this->_t0);
110  if (filename) {
111  mtx.lock();
112  if (!stream.is_open()) { stream.open(filename); }
113  stream << this->_tag << ' ';
114  traits_type::print(stream,this->_params);
115  stream << ' ' << dt.count() << std::endl;
116  mtx.unlock();
117  }
118  }
119 
120  };
121 
122  template <class ... Args>
123  inline Benchmark<Args...>
124  make_benchmark(const char* tag, Args... args) {
125  return Benchmark<Args...>(tag, args...);
126  }
127 
128  }
129 
130 }
131 
132 #define VTB_PROFILE_BLOCK(tag) \
133  ::vtb::profile::Profile __profile_ ## __LINE__{tag}
134 
135 #define VTB_BENCHMARK_BLOCK(tag, ...) \
136  auto __benchmark_ ## __LINE__ = ::vtb::profile::make_benchmark(tag,__VA_ARGS__)
137 
138 #else
139 
140 #define VTB_PROFILE_BLOCK(tag)
141 #define VTB_BENCHMARK_BLOCK(tag, ...)
142 
143 #endif
144 
145 #endif // vim:filetype=cpp
Record code block execution time.
Definition: profile.hh:51
Main namespace.
Definition: convert.hh:9