libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
latency_timestamps.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_LATENCY_TIMESTAMPS_HPP
2 #define LIBJMMCG_CORE_LATENCY_TIMESTAMPS_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2019 by J.M.McGuiness, coder@hussar.me.uk
6 **
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2.1 of the License, or (at your option) any later version.
11 **
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
22 #include "filename.hpp"
23 #include "hp_timer.hpp"
24 #include "non_allocatable.hpp"
25 
26 #include <iosfwd>
27 #include <memory>
28 
29 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
30 
32 public:
33  using size_type=std::size_t;
34  /**
35  Experimentation has indicated that using cpu_timer::out_of_order:
36  -# No statistical difference in performance, even with no time-stamping at all.
37  -# Worse statistics than the method chosen.
38 
39  \see cpu_timer::out_of_order
40  */
41  using timer_t=cpu_timer::in_order;
42  struct timestamp {
43  using element_type=cpu_timer::element_type;
44  /// The raw timestamp from the selected timer_t.
45  /**
46  \see timer_t
47  */
48  element_type start{};
49  /// The raw timestamp from the selected timer_t.
50  /**
51  \see timer_t
52  */
53  element_type end{};
54 
55  bool is_valid() const noexcept(true);
56  /// Write a timestamp to the output stream in CSV format.
57  /**
58  The output timestamps are in microseconds since the start of the program.
59  */
60  void to_csv(std::ostream &os) const noexcept(false);
61  };
62  using element_type=timestamp;
63  /**
64  Designed to assign to the huge collection of timestamps in the dtor, to avoid using it in the hot-path.
65  */
66  class ALIGN_TO_L1_CACHE period final : private non_newable {
67  public:
68  explicit REALLY_FORCE_INLINE period(latency_timestamps_itf &lts) noexcept(true);
69  REALLY_FORCE_INLINE ~period() noexcept(true);
70 
71  private:
72  element_type ts;
74  };
75 
76  virtual ~latency_timestamps_itf()=default;
77 
78  virtual void push_back(element_type const &ts) noexcept(true)=0;
79 
80 protected:
82 };
83 
84 /// A simple class that is used to create a CSV-formatted file of timestamps, from which a histogram might be generated.
85 /**
86  Compatible with no_latency_timestamps.
87 
88  \see no_latency_timestamps
89 */
90 class latency_timestamps final : public latency_timestamps_itf {
91 public:
92  explicit latency_timestamps(size_type num_tses) noexcept(false);
93 
94  size_type size() const noexcept(true);
95  /// Add a timestamp on the hot-path.
96  /**
97  As this is on the hot-path minimal processing is done. The location to be written to is loaded using a technique that minimises cache usage: this might be slightly slower, but attempts to avoid overwriting the entire contents of each cache in the hierarchy.
98  Note that this function is thread-safe & re-entrant safe.
99  */
100  REALLY_FORCE_INLINE void push_back(element_type const &ts) noexcept(true) override;
101 
102  /// Write the timestamps, if any, to the output-stream.
103  /**
104  \param os The output stream to which the timestamps, in CSV format, should be written.
105  */
106  void to_csv(std::ostream &os) const noexcept(false);
107  /// Wrtie the timestamps, if any, to a CSV file.
108  /**
109  \param os Write log output to this output stream.
110  \param root Write the timestamps, in CSV format, to a file with the filename root as specified. Unique identifying text will be appended and ".csv" shall be the extension.
111 
112  \see make_filename()
113  */
114  void write_to_csv_file(std::ostream &os, char const * const root) const noexcept(false);
115  /// Wrtie the timestamps, if any, to the named CSV file.
116  /**
117  \param os Write log output to this output stream.
118  \param base_filename Write the timestamps, in CSV format, to a file with the base of the filename as specified, the extension ".csv" will be appended.
119  */
120  void write_to_named_csv_file(std::ostream &os, std::string const &base_filename) const noexcept(false);
121 
122 private:
123  /**
124  Ideally this should be allocated in non-cacheable memory, as it is only written to once on the hot path.
125  */
126  std::unique_ptr<element_type[]> timestamps;
127  std::atomic<element_type*> current_timestamp;
128  const size_type num_timestamps;
129 };
130 
131 /// A simple class that is used to create no timestamps.
132 /**
133  Compatible with latency_timestamps.
134 
135  \see latency_timestamps
136 */
137 class no_latency_timestamps final : public latency_timestamps_itf {
138 public:
139  explicit no_latency_timestamps(std::size_t) noexcept(true) {}
140 
141  constexpr size_type size() const noexcept(true) {return 0;}
142  void push_back(element_type const &) noexcept(true) override {}
143 
144  void to_csv(std::ostream &) const noexcept(true) {}
145  void write_to_csv_file(std::ostream &, char const * const) const noexcept(true) {}
146  void write_to_named_csv_file(std::ostream &, std::string const &) const noexcept(true) {}
147 };
148 
149 } }
150 
152 
153 #endif