21#include <unordered_set>
25#include "absl/strings/str_cat.h"
34 "Name of the latency monitor.");
37 "Latency report interval in seconds.");
40 "Latency report interval in seconds.");
43 "The max message numbers in latency reader queue.");
55LatencyStat GenerateStat(
const std::vector<uint64_t>& numbers) {
57 uint64_t min_number = (1UL << 63), max_number = 0, sum = 0;
58 for (
const auto number : numbers) {
59 min_number = std::min(min_number, number);
60 max_number = std::max(max_number, number);
63 const uint32_t sample_size =
static_cast<uint32_t
>(numbers.size());
64 stat.set_min_duration(min_number);
65 stat.set_max_duration(max_number);
66 stat.set_aver_duration(
67 sample_size == 0 ? 0 : static_cast<uint64_t>(sum / sample_size));
68 stat.set_sample_size(sample_size);
72void SetStat(
const LatencyStat& src, LatencyStat* dst) {
73 dst->set_min_duration(src.min_duration());
74 dst->set_max_duration(src.max_duration());
75 dst->set_aver_duration(src.aver_duration());
76 dst->set_sample_size(src.sample_size());
79void SetLatency(
const std::string& latency_name,
80 const std::vector<uint64_t>& latency_values,
81 LatencyTrack* track) {
82 auto* latency_track = track->add_latency_track();
83 latency_track->set_latency_name(latency_name);
84 SetStat(GenerateStat(latency_values), latency_track->mutable_latency_stat());
91 FLAGS_latency_monitor_interval) {}
95 MonitorManager::Instance()->CreateReader<LatencyRecordMap>(
96 FLAGS_latency_recording_topic);
97 reader->SetHistoryDepth(FLAGS_latency_reader_capacity);
100 static std::string last_processed_key;
101 std::string first_key_of_current_round;
102 for (
auto it = reader->Begin(); it != reader->End(); ++it) {
103 const std::string current_key =
104 absl::StrCat((*it)->module_name(), (*it)->header().sequence_num());
105 if (it == reader->Begin()) {
106 first_key_of_current_round = current_key;
108 if (current_key == last_processed_key) {
113 last_processed_key = first_key_of_current_round;
115 if (current_time - flush_time_ > FLAGS_latency_report_interval) {
116 flush_time_ = current_time;
117 if (!track_map_.empty()) {
118 PublishLatencyReport();
123void LatencyMonitor::UpdateStat(
124 const std::shared_ptr<LatencyRecordMap>& records) {
125 const auto module_name = records->module_name();
126 for (
const auto& record : records->latency_records()) {
127 track_map_[record.message_id()].emplace(record.begin_time(),
128 record.end_time(), module_name);
131 if (!records->latency_records().empty()) {
132 const auto begin_time = records->latency_records().begin()->begin_time();
133 const auto end_time = records->latency_records().rbegin()->end_time();
134 if (end_time > begin_time) {
135 freq_map_[module_name] =
136 records->latency_records().size() /
142void LatencyMonitor::PublishLatencyReport() {
143 static auto writer = MonitorManager::Instance()->CreateWriter<LatencyReport>(
144 FLAGS_latency_reporting_topic);
145 apollo::common::util::FillHeader(
"LatencyReport", &latency_report_);
147 writer->Write(latency_report_);
148 latency_report_.clear_header();
150 latency_report_.clear_modules_latency();
151 latency_report_.clear_e2es_latency();
154void LatencyMonitor::AggregateLatency() {
155 static const std::string kE2EStartPoint = FLAGS_pointcloud_topic;
156 std::unordered_map<std::string, std::vector<uint64_t>> modules_track;
157 std::unordered_map<std::string, std::vector<uint64_t>> e2es_track;
158 std::unordered_set<std::string> all_modules;
161 std::string module_name;
162 uint64_t begin_time = 0, end_time = 0;
163 for (
const auto& message : track_map_) {
164 auto iter = message.second.begin();
165 while (iter != message.second.end()) {
166 std::tie(begin_time, end_time, module_name) = *iter;
167 modules_track[module_name].push_back(end_time - begin_time);
168 all_modules.emplace(module_name);
173 std::unordered_map<std::string, uint64_t> e2e_latencies;
174 for (
const auto& message : track_map_) {
175 uint64_t e2e_begin_time = 0;
176 auto iter = message.second.begin();
177 e2e_latencies.clear();
178 while (iter != message.second.end()) {
179 std::tie(begin_time, std::ignore, module_name) = *iter;
180 if (e2e_begin_time == 0 && module_name == kE2EStartPoint) {
181 e2e_begin_time = begin_time;
182 }
else if (module_name != kE2EStartPoint && e2e_begin_time != 0 &&
183 e2e_latencies.find(module_name) == e2e_latencies.end()) {
184 const auto duration = begin_time - e2e_begin_time;
185 e2e_latencies[module_name] = duration;
186 e2es_track[module_name].push_back(duration);
205 auto* modules_latency = latency_report_.mutable_modules_latency();
206 for (
const auto& module : modules_track) {
207 SetLatency(module.first, module.second, modules_latency);
209 auto* e2es_latency = latency_report_.mutable_e2es_latency();
210 for (
const auto& e2e : e2es_track) {
211 SetLatency(absl::StrCat(kE2EStartPoint,
" -> ", e2e.first), e2e.second,
218 if (freq_map_.find(channel_name) == freq_map_.end()) {
221 *freq = freq_map_[channel_name];
Cyber has builtin time type Time.
double ToSecond() const
convert time to second.
void RunOnce(const double current_time) override
bool GetFrequency(const std::string &channel_name, double *freq)
DEFINE_int32(latency_reader_capacity, 30, "The max message numbers in latency reader queue.")
DEFINE_string(latency_monitor_name, "LatencyMonitor", "Name of the latency monitor.")
DEFINE_double(latency_monitor_interval, 1.5, "Latency report interval in seconds.")
Some string util functions.