18
18
* of the source tree.
19
19
*/
20
20
#include < iostream>
21
+ #include < limits>
21
22
22
23
#include < tbox/util/fs.h>
23
24
#include < tbox/util/string.h>
29
30
using namespace std ;
30
31
using namespace tbox ;
31
32
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
+
32
47
using StringVec = std::vector<std::string>;
48
+ using StatVec = std::vector<Stat>;
33
49
34
50
// ! start_time_us, duration_us, name_index, module_index, thread_index
35
51
using 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_
119
135
ReadRecordFile (records_dir + ' /' + record_file, func);
120
136
}
121
137
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
+
122
165
int main (int argc, char **argv)
123
166
{
124
167
if (argc < 2 ) {
@@ -146,6 +189,7 @@ int main(int argc, char **argv)
146
189
std::string names_filename = dir_path + " /names.txt" ;
147
190
std::string modules_filename = dir_path + " /modules.txt" ;
148
191
std::string threads_filename = dir_path + " /threads.txt" ;
192
+
149
193
StringVec name_vec, module_vec, thread_vec;
150
194
if (!util::fs::ReadAllLinesFromTextFile (names_filename, name_vec))
151
195
std::cerr << " Warn: load names.txt fail!" << std::endl;
@@ -161,8 +205,11 @@ int main(int argc, char **argv)
161
205
return 0 ;
162
206
}
163
207
208
+ std::vector<Stat> stat_vec (name_vec.size ());
209
+
164
210
writer.writeHeader ();
165
211
212
+ // ! 第一次遍历记录文件
166
213
ReadAllRecordFiles (records_dir, record_file_name_vec,
167
214
[&] (uint64_t start_ts_us, uint64_t duration_us, uint64_t name_index, uint64_t module_index, uint64_t thread_index) {
168
215
std::string name = " unknown-name" , thread = " unknown-thread" , module = " unknown-module" ;
@@ -177,10 +224,60 @@ int main(int argc, char **argv)
177
224
module = module_vec[module_index];
178
225
179
226
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);
180
265
}
181
266
);
182
267
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
+
183
276
writer.writeFooter ();
277
+
278
+ // ! 输出统计到 stat.txt
279
+ std::string stat_filename = dir_path + " /stat.txt" ;
280
+ DumpStatToFile (name_vec, stat_vec, stat_filename);
184
281
return 0 ;
185
282
}
186
283
0 commit comments