1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "dfx/trace_record/ffrt_trace_record.h"
16 #include <securec.h>
17 #include <sstream>
18 #include <fcntl.h>
19 #include <iomanip>
20 #include <sys/syscall.h>
21 #include <unistd.h>
22 #include "dfx/bbox/bbox.h"
23 
24 namespace ffrt {
25 const int COLUMN_WIDTH_3 = 3;
26 const int COLUMN_WIDTH_9 = 9;
27 const int COLUMN_WIDTH_10 = 10;
28 const int COLUMN_WIDTH_12 = 12;
29 const int COLUMN_WIDTH_13 = 13;
30 const int COLUMN_WIDTH_16 = 16;
31 const int COLUMN_WIDTH_18 = 18;
32 const int COLUMN_WIDTH_19 = 19;
33 const int COLUMN_WIDTH_22 = 22;
34 bool FFRTTraceRecord::ffrt_be_used_ = false;
35 int FFRTTraceRecord::g_recordMaxWorkerNumber_[QoS::MaxNum()] = {};
36 ffrt_record_task_counter_t FFRTTraceRecord::g_recordTaskCounter_[FFRTTraceRecord::TASK_TYPE_NUM][QoS::MaxNum()] = {};
37 ffrt_record_task_time_t FFRTTraceRecord::g_recordTaskTime_[FFRTTraceRecord::TASK_TYPE_NUM][QoS::MaxNum()] = {};
38 
39 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
DumpNormalTaskStatisticInfo(std::ostringstream & oss)40 void FFRTTraceRecord::DumpNormalTaskStatisticInfo(std::ostringstream& oss)
41 {
42     for (size_t i = 0; i < QoS::MaxNum(); i++) {
43         if (g_recordTaskCounter_[ffrt_normal_task][i].submitCounter <= 0) {
44             continue;
45         }
46         oss << std::setw(COLUMN_WIDTH_3) << i
47             << std::setw(COLUMN_WIDTH_9) << "normal"
48             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].submitCounter
49             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].enqueueCounter
50             << std::setw(COLUMN_WIDTH_12) << g_recordTaskCounter_[ffrt_normal_task][i].coSwitchCounter
51             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].doneCounter
52             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
53 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
54         unsigned int doneCount = g_recordTaskCounter_[ffrt_normal_task][i].doneCounter.load();
55         if (doneCount > 0) {
56             oss << std::setw(COLUMN_WIDTH_13) << g_recordMaxWorkerNumber_[i]
57                 << std::setw(COLUMN_WIDTH_16) << g_recordTaskTime_[ffrt_normal_task][i].maxWaitTime
58                 << std::setw(COLUMN_WIDTH_19) << g_recordTaskTime_[ffrt_normal_task][i].maxRunDuration
59                 << std::setw(COLUMN_WIDTH_16) << (g_recordTaskTime_[ffrt_normal_task][i].waitTime/doneCount)
60                 << std::setw(COLUMN_WIDTH_19) << (g_recordTaskTime_[ffrt_normal_task][i].runDuration/doneCount)
61                 << std::setw(COLUMN_WIDTH_18) << g_recordTaskTime_[ffrt_normal_task][i].waitTime
62                 << std::setw(COLUMN_WIDTH_22) << g_recordTaskTime_[ffrt_normal_task][i].runDuration;
63         }
64 #endif
65         oss << "\n";
66     }
67 }
68 
DumpQueueTaskStatisticInfo(std::ostringstream & oss)69 void FFRTTraceRecord::DumpQueueTaskStatisticInfo(std::ostringstream& oss)
70 {
71     for (size_t i = 0; i < QoS::MaxNum(); i++) {
72         if (g_recordTaskCounter_[ffrt_queue_task][i].submitCounter <= 0) {
73             continue;
74         }
75         oss << std::setw(COLUMN_WIDTH_3) << i
76             << std::setw(COLUMN_WIDTH_9) << "queue"
77             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].submitCounter
78             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].submitCounter
79             << std::setw(COLUMN_WIDTH_12) << g_recordTaskCounter_[ffrt_queue_task][i].coSwitchCounter
80             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].doneCounter
81             << std::setw(COLUMN_WIDTH_10) << (g_recordTaskCounter_[ffrt_queue_task][i].doneCounter +
82                 g_recordTaskCounter_[ffrt_queue_task][i].cancelCounter);
83 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
84         unsigned int doneCount = g_recordTaskCounter_[ffrt_queue_task][i].doneCounter.load();
85         if (doneCount > 0) {
86             oss << std::setw(COLUMN_WIDTH_13) << g_recordMaxWorkerNumber_[i]
87                 << std::setw(COLUMN_WIDTH_16) << g_recordTaskTime_[ffrt_queue_task][i].maxWaitTime
88                 << std::setw(COLUMN_WIDTH_19) << g_recordTaskTime_[ffrt_queue_task][i].maxRunDuration
89                 << std::setw(COLUMN_WIDTH_16) << (g_recordTaskTime_[ffrt_queue_task][i].waitTime/doneCount)
90                 << std::setw(COLUMN_WIDTH_19) << (g_recordTaskTime_[ffrt_queue_task][i].runDuration/doneCount)
91                 << std::setw(COLUMN_WIDTH_18) << g_recordTaskTime_[ffrt_queue_task][i].waitTime
92                 << std::setw(COLUMN_WIDTH_22) << g_recordTaskTime_[ffrt_queue_task][i].runDuration;
93         }
94 #endif
95         oss << "\n";
96     }
97 }
98 
DumpUVTaskStatisticInfo(std::ostringstream & oss)99 void FFRTTraceRecord::DumpUVTaskStatisticInfo(std::ostringstream& oss)
100 {
101     for (size_t i = 0; i < QoS::MaxNum(); i++) {
102         if (g_recordTaskCounter_[ffrt_uv_task][i].submitCounter <= 0) {
103             continue;
104         }
105         oss << std::setw(COLUMN_WIDTH_3) << i
106             << std::setw(COLUMN_WIDTH_9) << "uv"
107             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].submitCounter
108             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].enqueueCounter
109             << std::setw(COLUMN_WIDTH_12) << 0
110             << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].doneCounter
111             << std::setw(COLUMN_WIDTH_10) << (g_recordTaskCounter_[ffrt_uv_task][i].doneCounter +
112                 g_recordTaskCounter_[ffrt_uv_task][i].cancelCounter);
113         oss << "\n";
114     }
115 }
116 
StatisticInfoDump(char * buf,uint32_t len)117 int FFRTTraceRecord::StatisticInfoDump(char* buf, uint32_t len)
118 {
119     std::ostringstream oss;
120     oss << "---\n" << "Qos TaskType SubmitNum EnueueNum CoSwitchNum   DoneNum FinishNum";
121 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
122     oss << " MaxWorkerNum MaxWaitTime(us) MaxRunDuration(us) AvgWaitTime(us) AvgRunDuration(us) TotalWaitTime(us)"
123         << "  TotalRunDuration(us)";
124 #endif
125     oss << "\n";
126     DumpNormalTaskStatisticInfo(oss);
127     DumpQueueTaskStatisticInfo(oss);
128     DumpUVTaskStatisticInfo(oss);
129     oss << "---\n";
130     return snprintf_s(buf, len, len - 1, "%s", oss.str().c_str());
131 }
132 
GetSubmitCount()133 unsigned int FFRTTraceRecord::GetSubmitCount()
134 {
135     int maxQos = QoS::MaxNum();
136     unsigned int totalCount = 0;
137     for (int i = 0; i < maxQos; i++) {
138         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].submitCounter;
139         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].submitCounter;
140         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].submitCounter;
141     }
142     return totalCount;
143 }
144 
GetEnqueueCount()145 unsigned int FFRTTraceRecord::GetEnqueueCount()
146 {
147     int maxQos = QoS::MaxNum();
148     unsigned int totalCount = 0;
149     for (int i = 0; i < maxQos; i++) {
150         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].enqueueCounter;
151         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].enqueueCounter;
152         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].enqueueCounter;
153     }
154     return totalCount;
155 }
156 
GetRunCount()157 unsigned int FFRTTraceRecord::GetRunCount()
158 {
159     int maxQos = QoS::MaxNum();
160     unsigned int totalCount = 0;
161     for (int i = 0; i < maxQos; i++) {
162         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].runCounter;
163         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].runCounter;
164         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].runCounter;
165     }
166     return totalCount;
167 }
168 
GetDoneCount()169 unsigned int FFRTTraceRecord::GetDoneCount()
170 {
171     int maxQos = QoS::MaxNum();
172     unsigned int totalCount = 0;
173     for (int i = 0; i < maxQos; i++) {
174         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
175         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].doneCounter;
176         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].doneCounter;
177     }
178     return totalCount;
179 }
180 
GetCoSwitchCount()181 unsigned int FFRTTraceRecord::GetCoSwitchCount()
182 {
183     int maxQos = QoS::MaxNum();
184     unsigned int totalCount = 0;
185     for (int i = 0; i < maxQos; i++) {
186         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].coSwitchCounter;
187         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].coSwitchCounter;
188     }
189     return totalCount;
190 }
191 
GetFinishCount()192 unsigned int FFRTTraceRecord::GetFinishCount()
193 {
194     int maxQos = QoS::MaxNum();
195     unsigned int totalCount = 0;
196     for (int i = 0; i < maxQos; i++) {
197         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
198         totalCount += g_recordTaskCounter_[ffrt_normal_task][i].cancelCounter;
199         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].doneCounter;
200         totalCount += g_recordTaskCounter_[ffrt_uv_task][i].cancelCounter;
201         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].doneCounter;
202         totalCount += g_recordTaskCounter_[ffrt_queue_task][i].cancelCounter;
203     }
204     return totalCount;
205 }
206 #endif // FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2
207 }