1818 * of the source tree.
1919 */
2020#include < iostream>
21+ #include < limits>
2122
2223#include < tbox/util/fs.h>
2324#include < tbox/util/string.h>
2930using namespace std ;
3031using namespace tbox ;
3132
33+ // ! 统计
34+ struct Stat {
35+ size_t times = 0 ; // ! 次数
36+ uint64_t dur_acc_us = 0 ; // ! 累积时长
37+ uint64_t dur_min_us = std::numeric_limits<uint64_t >::max(); // ! 最小时长
38+ uint64_t dur_max_us = 0 ; // ! 最大时长
39+ uint64_t dur_max_ts_us = 0 ; // ! 最大时长的时间点
40+
41+ uint64_t dur_avg_us = 0 ; // ! 平均时长
42+ uint64_t dur_warn_line_us = 0 ; // ! 警告水位线
43+
44+ uint64_t dur_warn_count = 0 ; // ! 超过警告水位线次数
45+ };
46+
3247using StringVec = std::vector<std::string>;
48+ using StatVec = std::vector<Stat>;
3349
3450// ! start_time_us, duration_us, name_index, module_index, thread_index
3551using RecordHandleFunc = std::function<void (uint64_t , uint64_t , uint64_t , uint64_t , uint64_t )>;
@@ -119,6 +135,33 @@ void ReadAllRecordFiles(const std::string &records_dir, const StringVec &record_
119135 ReadRecordFile (records_dir + ' /' + record_file, func);
120136}
121137
138+ void DumpStatToFile (const StringVec &name_vec, const StatVec &stat_vec, const std::string &stat_filename)
139+ {
140+ std::ofstream ofs (stat_filename);
141+ if (!ofs) {
142+ std::cout << " Error: open stat file '" << stat_filename << " ' fail!" << std::endl;
143+ return ;
144+ }
145+
146+ auto size = name_vec.size ();
147+ for (size_t i = 0 ; i < size; ++i) {
148+ auto &name = name_vec.at (i);
149+ auto &stat = stat_vec.at (i);
150+
151+ ofs << std::string (name.size (), ' =' ) << std::endl
152+ << name << std::endl
153+ << std::string (name.size (), ' -' ) << std::endl
154+ << " times : " << stat.times << std::endl
155+ << " dur_min_us : " << stat.dur_min_us << " us" << std::endl
156+ << " dur_avg_us : " << stat.dur_avg_us << " us" << std::endl
157+ << " dur_max_us : " << stat.dur_max_us << " us" << std::endl
158+ << " dur_max_at_us : " << stat.dur_max_ts_us << " us" << std::endl
159+ << " dur_warn_line_us : " << stat.dur_warn_line_us << " us" << std::endl
160+ << " dur_warn_count : " << stat.dur_warn_count << std::endl
161+ << std::endl;
162+ }
163+ }
164+
122165int main (int argc, char **argv)
123166{
124167 if (argc < 2 ) {
@@ -146,6 +189,7 @@ int main(int argc, char **argv)
146189 std::string names_filename = dir_path + " /names.txt" ;
147190 std::string modules_filename = dir_path + " /modules.txt" ;
148191 std::string threads_filename = dir_path + " /threads.txt" ;
192+
149193 StringVec name_vec, module_vec, thread_vec;
150194 if (!util::fs::ReadAllLinesFromTextFile (names_filename, name_vec))
151195 std::cerr << " Warn: load names.txt fail!" << std::endl;
@@ -161,8 +205,11 @@ int main(int argc, char **argv)
161205 return 0 ;
162206 }
163207
208+ std::vector<Stat> stat_vec (name_vec.size ());
209+
164210 writer.writeHeader ();
165211
212+ // ! 第一次遍历记录文件
166213 ReadAllRecordFiles (records_dir, record_file_name_vec,
167214 [&] (uint64_t start_ts_us, uint64_t duration_us, uint64_t name_index, uint64_t module_index, uint64_t thread_index) {
168215 std::string name = " unknown-name" , thread = " unknown-thread" , module = " unknown-module" ;
@@ -177,10 +224,60 @@ int main(int argc, char **argv)
177224 module = module_vec[module_index];
178225
179226 writer.writeRecorder (name, module , thread, start_ts_us, duration_us);
227+
228+ auto &stat = stat_vec.at (name_index);
229+ ++stat.times ;
230+ stat.dur_acc_us += duration_us;
231+ if (stat.dur_max_us < duration_us) {
232+ stat.dur_max_us = duration_us;
233+ stat.dur_max_ts_us = start_ts_us;
234+ }
235+
236+ if (stat.dur_min_us > duration_us) {
237+ stat.dur_min_us = duration_us;
238+ }
239+ }
240+ );
241+
242+ // ! 处理统计数据
243+ for (auto &stat : stat_vec) {
244+ stat.dur_avg_us = stat.dur_acc_us / stat.times ;
245+ stat.dur_warn_line_us = (stat.dur_avg_us + stat.dur_max_us ) / 2 ;
246+ }
247+
248+ // ! 第二次遍历记录文件,标出超出警告线的
249+ ReadAllRecordFiles (records_dir, record_file_name_vec,
250+ [&] (uint64_t start_ts_us, uint64_t duration_us, uint64_t name_index, uint64_t module_index, uint64_t ) {
251+ auto &stat = stat_vec.at (name_index);
252+ if (duration_us < stat.dur_warn_line_us )
253+ return ;
254+
255+ std::string name = " unknown-name" , module = " unknown-module" ;
256+
257+ if (name_index < name_vec.size ())
258+ name = name_vec[name_index];
259+
260+ if (module_index < module_vec.size ())
261+ module = module_vec[module_index];
262+
263+ ++stat.dur_warn_count ;
264+ writer.writeRecorder (name, module , " WARN" , start_ts_us, duration_us);
180265 }
181266 );
182267
268+ // ! 标记出最大时间点
269+ auto size = name_vec.size ();
270+ for (size_t i = 0 ; i < size; ++i) {
271+ auto &name = name_vec.at (i);
272+ auto &stat = stat_vec.at (i);
273+ writer.writeRecorder (name, " " , " MAX" , stat.dur_max_ts_us , stat.dur_max_us );
274+ }
275+
183276 writer.writeFooter ();
277+
278+ // ! 输出统计到 stat.txt
279+ std::string stat_filename = dir_path + " /stat.txt" ;
280+ DumpStatToFile (name_vec, stat_vec, stat_filename);
184281 return 0 ;
185282}
186283
0 commit comments