Apollo 10.0
自动驾驶开放平台
latency_monitor.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <memory>
21#include <unordered_set>
22#include <utility>
23#include <vector>
24
25#include "absl/strings/str_cat.h"
26#include "cyber/common/log.h"
27#include "cyber/time/time.h"
32
33DEFINE_string(latency_monitor_name, "LatencyMonitor",
34 "Name of the latency monitor.");
35
36DEFINE_double(latency_monitor_interval, 1.5,
37 "Latency report interval in seconds.");
38
39DEFINE_double(latency_report_interval, 15.0,
40 "Latency report interval in seconds.");
41
42DEFINE_int32(latency_reader_capacity, 30,
43 "The max message numbers in latency reader queue.");
44
45namespace apollo {
46namespace monitor {
47
48namespace {
49
54
55LatencyStat GenerateStat(const std::vector<uint64_t>& numbers) {
56 LatencyStat stat;
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);
61 sum += number;
62 }
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);
69 return stat;
70}
71
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());
77}
78
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());
85}
86
87} // namespace
88
90 : RecurrentRunner(FLAGS_latency_monitor_name,
91 FLAGS_latency_monitor_interval) {}
92
93void LatencyMonitor::RunOnce(const double current_time) {
94 static auto reader =
95 MonitorManager::Instance()->CreateReader<LatencyRecordMap>(
96 FLAGS_latency_recording_topic);
97 reader->SetHistoryDepth(FLAGS_latency_reader_capacity);
98 reader->Observe();
99
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;
107 }
108 if (current_key == last_processed_key) {
109 break;
110 }
111 UpdateStat(*it);
112 }
113 last_processed_key = first_key_of_current_round;
114
115 if (current_time - flush_time_ > FLAGS_latency_report_interval) {
116 flush_time_ = current_time;
117 if (!track_map_.empty()) {
118 PublishLatencyReport();
119 }
120 }
121}
122
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);
129 }
130
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() /
137 apollo::cyber::Time(end_time - begin_time).ToSecond();
138 }
139 }
140}
141
142void LatencyMonitor::PublishLatencyReport() {
143 static auto writer = MonitorManager::Instance()->CreateWriter<LatencyReport>(
144 FLAGS_latency_reporting_topic);
145 apollo::common::util::FillHeader("LatencyReport", &latency_report_);
146 AggregateLatency();
147 writer->Write(latency_report_);
148 latency_report_.clear_header();
149 track_map_.clear();
150 latency_report_.clear_modules_latency();
151 latency_report_.clear_e2es_latency();
152}
153
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;
159
160 // Aggregate modules latencies
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);
169 ++iter;
170 }
171 }
172 // Aggregate E2E latencies
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);
187 }
188 ++iter;
189 }
190 }
191
192 // The results could be in the following fromat:
193 // e2e latency:
194 // pointcloud -> perception: min(500), max(600), average(550),
195 // sample_size(1500) pointcloud -> planning: min(800), max(1000),
196 // average(900), sample_size(1500) pointcloud -> control: min(1200),
197 // max(1300), average(1250), sample_size(1500)
198 // ...
199 // modules latency:
200 // perception: min(5), max(50), average(30), sample_size(1000)
201 // prediction: min(500), max(5000), average(2000), sample_size(800)
202 // control: min(500), max(800), average(600), sample_size(800)
203 // ...
204
205 auto* modules_latency = latency_report_.mutable_modules_latency();
206 for (const auto& module : modules_track) {
207 SetLatency(module.first, module.second, modules_latency);
208 }
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,
212 e2es_latency);
213 }
214}
215
216bool LatencyMonitor::GetFrequency(const std::string& channel_name,
217 double* freq) {
218 if (freq_map_.find(channel_name) == freq_map_.end()) {
219 return false;
220 }
221 *freq = freq_map_[channel_name];
222 return true;
223}
224
225} // namespace monitor
226} // namespace apollo
Cyber has builtin time type Time.
Definition time.h:31
double ToSecond() const
convert time to second.
Definition time.cc:77
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.")
class register implement
Definition arena_queue.h:37
Some string util functions.