1 /*
2 * Copyright (c) 2024 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
16 #include "libpandabase/taskmanager/utils/task_time_stats.h"
17 #include "libpandabase/utils/time.h"
18
19 #include <sstream>
20 #include <numeric>
21 #include <cmath>
22 #include <ostream>
23
24 namespace ark::taskmanager {
25
StringToTaskTimeStats(std::string_view str)26 TaskTimeStatsType StringToTaskTimeStats(std::string_view str)
27 {
28 if (str == "no-task-stats") {
29 return TaskTimeStatsType::NO_STATISTICS;
30 }
31 if (str == "light-task-stats") {
32 return TaskTimeStatsType::LIGHT_STATISTICS;
33 }
34 UNREACHABLE();
35 }
36
operator <<(std::ostream & os,TaskTimeStatsType type)37 std::ostream &operator<<(std::ostream &os, TaskTimeStatsType type)
38 {
39 switch (type) {
40 case TaskTimeStatsType::NO_STATISTICS:
41 os << "TaskTimeStatsType::NO_STATISTICS";
42 break;
43 case TaskTimeStatsType::LIGHT_STATISTICS:
44 os << "TaskTimeStatsType::LIGHT_STATISTICS";
45 break;
46 default:
47 UNREACHABLE();
48 break;
49 }
50 return os;
51 }
52
53 thread_local TaskTimeStatsBase::ContainerId TaskTimeStatsBase::containerId_ = TaskTimeStatsBase::DEFAULT_CONTAINER_ID;
54
RegisterWorkerThread()55 void TaskTimeStatsBase::RegisterWorkerThread()
56 {
57 // Atomic with acq_rel order reason: fetch_add operation should be sync with calls from other threads
58 size_t registerNumber = countOfRegisteredWorkers_.fetch_add(1, std::memory_order_acq_rel);
59 containerId_ = registerNumber + 1U;
60 }
61
62 namespace internal {
63
LightTaskTimeTimeStats(size_t countOfWorkers)64 LightTaskTimeTimeStats::LightTaskTimeTimeStats(size_t countOfWorkers)
65 : statisticsContainerPerThread_(countOfWorkers + 1U)
66 {
67 for (auto &statisticsContainer : statisticsContainerPerThread_) {
68 for (size_t i = 0; i < STATISTICS_CONTAINER_SIZE; i++) {
69 statisticsContainer[i] = MeanTimeStats();
70 }
71 }
72 }
73
CollectLifeAndExecutionTimes(TaskProperties prop,uint64_t lifeTime,uint64_t executionTime)74 void LightTaskTimeTimeStats::CollectLifeAndExecutionTimes(TaskProperties prop, uint64_t lifeTime,
75 uint64_t executionTime)
76 {
77 auto propHash = TaskProperties::Hash()(prop);
78 auto &meanTimeStats = statisticsContainerPerThread_[containerId_][propHash];
79
80 meanTimeStats.sumExecutionTime += executionTime;
81 meanTimeStats.sumLifeTime += lifeTime;
82
83 meanTimeStats.maxExecutionTime = std::max(executionTime, meanTimeStats.maxExecutionTime);
84 meanTimeStats.maxLifeTime = std::max(lifeTime, meanTimeStats.maxLifeTime);
85
86 ASSERT(meanTimeStats.sumLifeTime >= meanTimeStats.sumExecutionTime);
87
88 meanTimeStats.countOfTasks++;
89 }
90
GetTaskStatistics()91 std::vector<std::string> LightTaskTimeTimeStats::GetTaskStatistics()
92 {
93 std::vector<std::string> resultData;
94 for (auto prop : GetAllTaskProperties()) {
95 if (GetCountOfTasksWithProperties(prop) == 0) {
96 continue;
97 }
98 resultData.push_back(GetStatisticsForProperties(prop));
99 }
100 return resultData;
101 }
102
GetAllTaskProperties()103 std::vector<TaskProperties> LightTaskTimeTimeStats::GetAllTaskProperties()
104 {
105 std::vector<TaskProperties> allTaskProperties;
106 for (TaskType taskType : ALL_TASK_TYPES) {
107 for (VMType vmType : ALL_VM_TYPES) {
108 for (TaskExecutionMode executionMode : ALL_TASK_EXECUTION_MODES) {
109 allTaskProperties.emplace_back(taskType, vmType, executionMode);
110 }
111 }
112 }
113 return allTaskProperties;
114 }
115
GetStatisticsForProperties(TaskProperties prop)116 std::string LightTaskTimeTimeStats::GetStatisticsForProperties(TaskProperties prop)
117 {
118 std::stringstream stream;
119 auto propHash = TaskProperties::Hash()(prop);
120 uint64_t sumLifeTime = 0;
121 uint64_t sumExecutionTime = 0;
122 uint64_t maxLifeTime = 0;
123 uint64_t maxExecutionTime = 0;
124 size_t sumTaskCount = 0;
125 for (const auto &statisticsContainer : statisticsContainerPerThread_) {
126 const auto &meanStatistics = statisticsContainer[propHash];
127 sumLifeTime += meanStatistics.sumLifeTime;
128 sumExecutionTime += meanStatistics.sumExecutionTime;
129
130 maxLifeTime = std::max(meanStatistics.maxLifeTime, maxLifeTime);
131 maxExecutionTime = std::max(meanStatistics.maxExecutionTime, maxExecutionTime);
132
133 sumTaskCount += meanStatistics.countOfTasks;
134 }
135 auto meanLifeTime = static_cast<double>(sumLifeTime) / sumTaskCount;
136 auto meanExecutionTime = static_cast<double>(sumExecutionTime) / sumTaskCount;
137 stream << "Task " << prop << ": mean life time: " << meanLifeTime << "us; max life time: " << maxLifeTime
138 << "us; mean execution time: " << meanExecutionTime << "us; "
139 << "max execution time: " << maxExecutionTime << "us; count of tasks: " << sumTaskCount << ";";
140 return stream.str();
141 }
142
GetCountOfTasksWithProperties(TaskProperties prop)143 size_t LightTaskTimeTimeStats::GetCountOfTasksWithProperties(TaskProperties prop)
144 {
145 auto propHash = TaskProperties::Hash()(prop);
146 size_t sumTaskCount = 0;
147 for (const auto &statisticsContainer : statisticsContainerPerThread_) {
148 const auto &meanStatistics = statisticsContainer[propHash];
149 sumTaskCount += meanStatistics.countOfTasks;
150 }
151 return sumTaskCount;
152 }
153
154 } // namespace internal
155
156 } // namespace ark::taskmanager