blob: ef072544136bc4fdab5cbde1be2e57314eba0449 [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
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08009namespace aos::internal {
Austin Schuhe4106142019-12-01 18:19:53 -080010
11// Class to compute statistics for the timing report.
12class TimingStatistic {
13 public:
14 TimingStatistic() {}
15
16 // Sets the flatbuffer to mutate.
17 void set_statistic(timing::Statistic *statistic) { statistic_ = statistic; }
18
19 // Adds a sample to the statistic.
20 void Add(float sample) {
Brian Silvermanbf889922021-11-10 12:41:57 -080021 if (!statistic_) {
22 return;
23 }
24
Austin Schuhe4106142019-12-01 18:19:53 -080025 ++count_;
26 if (count_ == 1) {
27 statistic_->mutate_average(sample);
28 statistic_->mutate_min(sample);
29 statistic_->mutate_max(sample);
30 statistic_->mutate_standard_deviation(0.0);
31 } else {
32 // https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
33 const float prior_average = statistic_->average();
34 const float average = prior_average + (sample - prior_average) / count_;
35 statistic_->mutate_average(average);
36 statistic_->mutate_max(std::max(statistic_->max(), sample));
37 statistic_->mutate_min(std::min(statistic_->min(), sample));
38
39 Q_ = Q_ + (sample - prior_average) * (sample - average);
40 statistic_->mutate_standard_deviation(std::sqrt(Q_ / (count_ - 1)));
41 }
42 }
43
44 // Clears any accumulated statistics.
45 void Reset() {
Brian Silvermanbf889922021-11-10 12:41:57 -080046 if (!statistic_) {
47 return;
48 }
49
Austin Schuhe4106142019-12-01 18:19:53 -080050 statistic_->mutate_average(std::numeric_limits<float>::quiet_NaN());
51 statistic_->mutate_min(std::numeric_limits<float>::quiet_NaN());
52 statistic_->mutate_max(std::numeric_limits<float>::quiet_NaN());
53
54 statistic_->mutate_standard_deviation(
55 std::numeric_limits<float>::quiet_NaN());
56 Q_ = 0;
57 count_ = 0;
58 }
59
60 private:
61 timing::Statistic *statistic_ = nullptr;
62 // Number of samples accumulated.
63 size_t count_ = 0;
64 // State Q from wikipedia.
65 float Q_ = 0.0;
66};
67
68// Class to hold timing information for a raw fetcher.
69struct RawFetcherTiming {
70 RawFetcherTiming(int new_channel_index) : channel_index(new_channel_index) {}
71
72 void set_timing_report(timing::Fetcher *fetcher);
73 void ResetTimingReport();
74
75 const int channel_index;
76 timing::Fetcher *fetcher = nullptr;
77 internal::TimingStatistic latency;
78};
79
80// Class to hold timing information for a raw sender.
81struct RawSenderTiming {
James Kuszmaulcc94ed42022-08-24 11:36:17 -070082 typedef util::ErrorCounter<timing::SendError, timing::SendErrorCount>
83 ErrorCounter;
84 static constexpr size_t kNumErrors = ErrorCounter::kNumErrors;
James Kuszmaul78514332022-04-06 15:08:34 -070085
Austin Schuhe4106142019-12-01 18:19:53 -080086 RawSenderTiming(int new_channel_index) : channel_index(new_channel_index) {}
87
88 void set_timing_report(timing::Sender *sender);
89 void ResetTimingReport();
James Kuszmaul78514332022-04-06 15:08:34 -070090 void IncrementError(timing::SendError error);
91 // Sanity check that the enum values are such that we can just use the enum
92 // values themselves as array indices without anything weird happening.
James Kuszmaul78514332022-04-06 15:08:34 -070093 static_assert(
94 sizeof(std::invoke_result<decltype(timing::EnumValuesSendError)>::type) /
95 sizeof(timing::SendError) ==
96 kNumErrors,
97 "Expected continguous enum values.");
Austin Schuhe4106142019-12-01 18:19:53 -080098
99 const int channel_index;
100 timing::Sender *sender = nullptr;
101 internal::TimingStatistic size;
James Kuszmaulcc94ed42022-08-24 11:36:17 -0700102 ErrorCounter error_counter;
Austin Schuhe4106142019-12-01 18:19:53 -0800103};
104
105// Class to hold timing information for timers.
106struct TimerTiming {
107 void set_timing_report(timing::Timer *timer);
108 void ResetTimingReport();
109
110 internal::TimingStatistic wakeup_latency;
111 internal::TimingStatistic handler_time;
112 timing::Timer *timer = nullptr;
113};
114
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800115} // namespace aos::internal
Austin Schuhe4106142019-12-01 18:19:53 -0800116
117#endif // AOS_EVENTS_TIMING_STATISTICS_H_