blob: 3c8c741f3fe9e54492f2c3877984d85941d22a6f [file] [log] [blame]
Austin Schuhe4106142019-12-01 18:19:53 -08001#ifndef AOS_EVENTS_TIMING_STATISTICS_H_
2#define AOS_EVENTS_TIMING_STATISTICS_H_
3
4#include <cmath>
5
6#include "aos/events/event_loop_generated.h"
James Kuszmaulcc94ed42022-08-24 11:36:17 -07007#include "aos/util/error_counter.h"
Austin Schuhe4106142019-12-01 18:19:53 -08008
9namespace aos {
10namespace internal {
11
12// Class to compute statistics for the timing report.
13class TimingStatistic {
14 public:
15 TimingStatistic() {}
16
17 // Sets the flatbuffer to mutate.
18 void set_statistic(timing::Statistic *statistic) { statistic_ = statistic; }
19
20 // Adds a sample to the statistic.
21 void Add(float sample) {
Brian Silvermanbf889922021-11-10 12:41:57 -080022 if (!statistic_) {
23 return;
24 }
25
Austin Schuhe4106142019-12-01 18:19:53 -080026 ++count_;
27 if (count_ == 1) {
28 statistic_->mutate_average(sample);
29 statistic_->mutate_min(sample);
30 statistic_->mutate_max(sample);
31 statistic_->mutate_standard_deviation(0.0);
32 } else {
33 // https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
34 const float prior_average = statistic_->average();
35 const float average = prior_average + (sample - prior_average) / count_;
36 statistic_->mutate_average(average);
37 statistic_->mutate_max(std::max(statistic_->max(), sample));
38 statistic_->mutate_min(std::min(statistic_->min(), sample));
39
40 Q_ = Q_ + (sample - prior_average) * (sample - average);
41 statistic_->mutate_standard_deviation(std::sqrt(Q_ / (count_ - 1)));
42 }
43 }
44
45 // Clears any accumulated statistics.
46 void Reset() {
Brian Silvermanbf889922021-11-10 12:41:57 -080047 if (!statistic_) {
48 return;
49 }
50
Austin Schuhe4106142019-12-01 18:19:53 -080051 statistic_->mutate_average(std::numeric_limits<float>::quiet_NaN());
52 statistic_->mutate_min(std::numeric_limits<float>::quiet_NaN());
53 statistic_->mutate_max(std::numeric_limits<float>::quiet_NaN());
54
55 statistic_->mutate_standard_deviation(
56 std::numeric_limits<float>::quiet_NaN());
57 Q_ = 0;
58 count_ = 0;
59 }
60
61 private:
62 timing::Statistic *statistic_ = nullptr;
63 // Number of samples accumulated.
64 size_t count_ = 0;
65 // State Q from wikipedia.
66 float Q_ = 0.0;
67};
68
69// Class to hold timing information for a raw fetcher.
70struct RawFetcherTiming {
71 RawFetcherTiming(int new_channel_index) : channel_index(new_channel_index) {}
72
73 void set_timing_report(timing::Fetcher *fetcher);
74 void ResetTimingReport();
75
76 const int channel_index;
77 timing::Fetcher *fetcher = nullptr;
78 internal::TimingStatistic latency;
79};
80
81// Class to hold timing information for a raw sender.
82struct RawSenderTiming {
James Kuszmaulcc94ed42022-08-24 11:36:17 -070083 typedef util::ErrorCounter<timing::SendError, timing::SendErrorCount>
84 ErrorCounter;
85 static constexpr size_t kNumErrors = ErrorCounter::kNumErrors;
James Kuszmaul78514332022-04-06 15:08:34 -070086
Austin Schuhe4106142019-12-01 18:19:53 -080087 RawSenderTiming(int new_channel_index) : channel_index(new_channel_index) {}
88
89 void set_timing_report(timing::Sender *sender);
90 void ResetTimingReport();
James Kuszmaul78514332022-04-06 15:08:34 -070091 void IncrementError(timing::SendError error);
92 // Sanity check that the enum values are such that we can just use the enum
93 // values themselves as array indices without anything weird happening.
James Kuszmaul78514332022-04-06 15:08:34 -070094 static_assert(
95 sizeof(std::invoke_result<decltype(timing::EnumValuesSendError)>::type) /
96 sizeof(timing::SendError) ==
97 kNumErrors,
98 "Expected continguous enum values.");
Austin Schuhe4106142019-12-01 18:19:53 -080099
100 const int channel_index;
101 timing::Sender *sender = nullptr;
102 internal::TimingStatistic size;
James Kuszmaulcc94ed42022-08-24 11:36:17 -0700103 ErrorCounter error_counter;
Austin Schuhe4106142019-12-01 18:19:53 -0800104};
105
106// Class to hold timing information for timers.
107struct TimerTiming {
108 void set_timing_report(timing::Timer *timer);
109 void ResetTimingReport();
110
111 internal::TimingStatistic wakeup_latency;
112 internal::TimingStatistic handler_time;
113 timing::Timer *timer = nullptr;
114};
115
116} // namespace internal
117} // namespace aos
118
119#endif // AOS_EVENTS_TIMING_STATISTICS_H_