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 <securec.h>
16 #include <sstream>
17 #include <fcntl.h>
18 #include <iomanip>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21 #include "dfx/bbox/bbox.h"
22 #include "dfx/trace_record/ffrt_trace_record.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 bool FFRTTraceRecord::stat_enable_ = false;
36 std::unique_ptr<FFRTRingBuffer> FFRTTraceRecord::ringBuffer_ = nullptr;
37 int FFRTTraceRecord::g_recordMaxWorkerNumber_[QoS::MaxNum()] = {};
38 ffrt_record_task_counter_t FFRTTraceRecord::g_recordTaskCounter_[FFRTTraceRecord::TASK_TYPE_NUM][QoS::MaxNum()] = {};
39 ffrt_record_task_time_t FFRTTraceRecord::g_recordTaskTime_[FFRTTraceRecord::TASK_TYPE_NUM][QoS::MaxNum()] = {};
40
41 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
DumpNormalTaskStatisticInfo(std::ostringstream & oss)42 void FFRTTraceRecord::DumpNormalTaskStatisticInfo(std::ostringstream& oss)
43 {
44 for (size_t i = 0; i < QoS::MaxNum(); i++) {
45 if (g_recordTaskCounter_[ffrt_normal_task][i].submitCounter <= 0) {
46 continue;
47 }
48 oss << std::setw(COLUMN_WIDTH_3) << i
49 << std::setw(COLUMN_WIDTH_9) << "normal"
50 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].submitCounter
51 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].enqueueCounter
52 << std::setw(COLUMN_WIDTH_12) << g_recordTaskCounter_[ffrt_normal_task][i].coSwitchCounter
53 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].doneCounter
54 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
55 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
56 unsigned int doneCount = g_recordTaskCounter_[ffrt_normal_task][i].doneCounter.load();
57 if (doneCount > 0) {
58 oss << std::setw(COLUMN_WIDTH_13) << g_recordMaxWorkerNumber_[i]
59 << std::setw(COLUMN_WIDTH_16) << g_recordTaskTime_[ffrt_normal_task][i].maxWaitTime
60 << std::setw(COLUMN_WIDTH_19) << g_recordTaskTime_[ffrt_normal_task][i].maxRunDuration
61 << std::setw(COLUMN_WIDTH_16) << (g_recordTaskTime_[ffrt_normal_task][i].waitTime/doneCount)
62 << std::setw(COLUMN_WIDTH_19) << (g_recordTaskTime_[ffrt_normal_task][i].runDuration/doneCount)
63 << std::setw(COLUMN_WIDTH_18) << g_recordTaskTime_[ffrt_normal_task][i].waitTime
64 << std::setw(COLUMN_WIDTH_22) << g_recordTaskTime_[ffrt_normal_task][i].runDuration;
65 }
66 #endif
67 oss << "\n";
68 }
69 }
70
DumpQueueTaskStatisticInfo(std::ostringstream & oss)71 void FFRTTraceRecord::DumpQueueTaskStatisticInfo(std::ostringstream& oss)
72 {
73 for (size_t i = 0; i < QoS::MaxNum(); i++) {
74 if (g_recordTaskCounter_[ffrt_queue_task][i].submitCounter <= 0) {
75 continue;
76 }
77 oss << std::setw(COLUMN_WIDTH_3) << i
78 << std::setw(COLUMN_WIDTH_9) << "queue"
79 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].submitCounter
80 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].submitCounter
81 << std::setw(COLUMN_WIDTH_12) << g_recordTaskCounter_[ffrt_queue_task][i].coSwitchCounter
82 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_queue_task][i].doneCounter
83 << std::setw(COLUMN_WIDTH_10) << (g_recordTaskCounter_[ffrt_queue_task][i].doneCounter +
84 g_recordTaskCounter_[ffrt_queue_task][i].cancelCounter);
85 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
86 unsigned int doneCount = g_recordTaskCounter_[ffrt_queue_task][i].doneCounter.load();
87 if (doneCount > 0) {
88 oss << std::setw(COLUMN_WIDTH_13) << g_recordMaxWorkerNumber_[i]
89 << std::setw(COLUMN_WIDTH_16) << g_recordTaskTime_[ffrt_queue_task][i].maxWaitTime
90 << std::setw(COLUMN_WIDTH_19) << g_recordTaskTime_[ffrt_queue_task][i].maxRunDuration
91 << std::setw(COLUMN_WIDTH_16) << (g_recordTaskTime_[ffrt_queue_task][i].waitTime/doneCount)
92 << std::setw(COLUMN_WIDTH_19) << (g_recordTaskTime_[ffrt_queue_task][i].runDuration/doneCount)
93 << std::setw(COLUMN_WIDTH_18) << g_recordTaskTime_[ffrt_queue_task][i].waitTime
94 << std::setw(COLUMN_WIDTH_22) << g_recordTaskTime_[ffrt_queue_task][i].runDuration;
95 }
96 #endif
97 oss << "\n";
98 }
99 }
100
DumpUVTaskStatisticInfo(std::ostringstream & oss)101 void FFRTTraceRecord::DumpUVTaskStatisticInfo(std::ostringstream& oss)
102 {
103 for (size_t i = 0; i < QoS::MaxNum(); i++) {
104 if (g_recordTaskCounter_[ffrt_uv_task][i].submitCounter <= 0) {
105 continue;
106 }
107 oss << std::setw(COLUMN_WIDTH_3) << i
108 << std::setw(COLUMN_WIDTH_9) << "uv"
109 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].submitCounter
110 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].enqueueCounter
111 << std::setw(COLUMN_WIDTH_12) << 0
112 << std::setw(COLUMN_WIDTH_10) << g_recordTaskCounter_[ffrt_uv_task][i].doneCounter
113 << std::setw(COLUMN_WIDTH_10) << (g_recordTaskCounter_[ffrt_uv_task][i].doneCounter +
114 g_recordTaskCounter_[ffrt_uv_task][i].cancelCounter);
115 oss << "\n";
116 }
117 }
118
StatisticInfoDump(char * buf,uint32_t len)119 int FFRTTraceRecord::StatisticInfoDump(char* buf, uint32_t len)
120 {
121 std::ostringstream oss;
122 oss << "---\n" << "Qos TaskType SubmitNum EnueueNum CoSwitchNum DoneNum FinishNum";
123 #if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
124 oss << " MaxWorkerNum MaxWaitTime(us) MaxRunDuration(us) AvgWaitTime(us) AvgRunDuration(us) TotalWaitTime(us)"
125 << " TotalRunDuration(us)";
126 #endif
127 oss << "\n";
128 DumpNormalTaskStatisticInfo(oss);
129 DumpQueueTaskStatisticInfo(oss);
130 DumpUVTaskStatisticInfo(oss);
131 oss << "---\n";
132 return snprintf_s(buf, len, len - 1, "%s", oss.str().c_str());
133 }
134
GetSubmitCount()135 unsigned int FFRTTraceRecord::GetSubmitCount()
136 {
137 int maxQos = QoS::MaxNum();
138 unsigned int totalCount = 0;
139 for (int i = 0; i < maxQos; i++) {
140 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].submitCounter;
141 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].submitCounter;
142 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].submitCounter;
143 }
144 return totalCount;
145 }
146
GetEnqueueCount()147 unsigned int FFRTTraceRecord::GetEnqueueCount()
148 {
149 int maxQos = QoS::MaxNum();
150 unsigned int totalCount = 0;
151 for (int i = 0; i < maxQos; i++) {
152 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].enqueueCounter;
153 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].enqueueCounter;
154 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].enqueueCounter;
155 }
156 return totalCount;
157 }
158
GetRunCount()159 unsigned int FFRTTraceRecord::GetRunCount()
160 {
161 int maxQos = QoS::MaxNum();
162 unsigned int totalCount = 0;
163 for (int i = 0; i < maxQos; i++) {
164 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].runCounter;
165 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].runCounter;
166 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].runCounter;
167 }
168 return totalCount;
169 }
170
GetDoneCount()171 unsigned int FFRTTraceRecord::GetDoneCount()
172 {
173 int maxQos = QoS::MaxNum();
174 unsigned int totalCount = 0;
175 for (int i = 0; i < maxQos; i++) {
176 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
177 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].doneCounter;
178 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].doneCounter;
179 }
180 return totalCount;
181 }
182
GetCoSwitchCount()183 unsigned int FFRTTraceRecord::GetCoSwitchCount()
184 {
185 int maxQos = QoS::MaxNum();
186 unsigned int totalCount = 0;
187 for (int i = 0; i < maxQos; i++) {
188 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].coSwitchCounter;
189 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].coSwitchCounter;
190 }
191 return totalCount;
192 }
193
GetFinishCount()194 unsigned int FFRTTraceRecord::GetFinishCount()
195 {
196 int maxQos = QoS::MaxNum();
197 unsigned int totalCount = 0;
198 for (int i = 0; i < maxQos; i++) {
199 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].doneCounter;
200 totalCount += g_recordTaskCounter_[ffrt_normal_task][i].cancelCounter;
201 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].doneCounter;
202 totalCount += g_recordTaskCounter_[ffrt_uv_task][i].cancelCounter;
203 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].doneCounter;
204 totalCount += g_recordTaskCounter_[ffrt_queue_task][i].cancelCounter;
205 }
206 return totalCount;
207 }
208 #endif // FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2
209 }