1 /*
2 * Copyright (c) 2024-2025 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(QueueId id,uint64_t lifeTime,uint64_t executionTime)74 void LightTaskTimeTimeStats::CollectLifeAndExecutionTimes(QueueId id, uint64_t lifeTime, uint64_t executionTime)
75 {
76 auto &meanTimeStats = statisticsContainerPerThread_[containerId_][id];
77
78 meanTimeStats.sumExecutionTime += executionTime;
79 meanTimeStats.sumLifeTime += lifeTime;
80
81 meanTimeStats.maxExecutionTime = std::max(executionTime, meanTimeStats.maxExecutionTime);
82 meanTimeStats.maxLifeTime = std::max(lifeTime, meanTimeStats.maxLifeTime);
83
84 ASSERT(meanTimeStats.sumLifeTime >= meanTimeStats.sumExecutionTime);
85
86 meanTimeStats.countOfTasks++;
87 }
88
GetTaskStatistics()89 std::vector<std::string> LightTaskTimeTimeStats::GetTaskStatistics()
90 {
91 std::vector<std::string> resultData;
92 for (QueueId id = 0; id < MAX_ID_COUNT; id++) {
93 if (GetCountOfTasksWithProperties(id) == 0) {
94 continue;
95 }
96 resultData.push_back(GetStatisticsForProperties(id));
97 }
98 return resultData;
99 }
100
GetStatisticsForProperties(QueueId id)101 std::string LightTaskTimeTimeStats::GetStatisticsForProperties(QueueId id)
102 {
103 std::stringstream stream;
104 uint64_t sumLifeTime = 0;
105 uint64_t sumExecutionTime = 0;
106 uint64_t maxLifeTime = 0;
107 uint64_t maxExecutionTime = 0;
108 size_t sumTaskCount = 0;
109 for (const auto &statisticsContainer : statisticsContainerPerThread_) {
110 const auto &meanStatistics = statisticsContainer[id];
111 sumLifeTime += meanStatistics.sumLifeTime;
112 sumExecutionTime += meanStatistics.sumExecutionTime;
113
114 maxLifeTime = std::max(meanStatistics.maxLifeTime, maxLifeTime);
115 maxExecutionTime = std::max(meanStatistics.maxExecutionTime, maxExecutionTime);
116
117 sumTaskCount += meanStatistics.countOfTasks;
118 }
119 auto meanLifeTime = static_cast<double>(sumLifeTime) / sumTaskCount;
120 auto meanExecutionTime = static_cast<double>(sumExecutionTime) / sumTaskCount;
121 stream << "TaskQueueId: " << id << "; mean life time: " << meanLifeTime << "us; max life time: " << maxLifeTime
122 << "us; mean execution time: " << meanExecutionTime << "us; "
123 << "max execution time: " << maxExecutionTime << "us; count of tasks: " << sumTaskCount << ";";
124 return stream.str();
125 }
126
GetCountOfTasksWithProperties(QueueId id)127 size_t LightTaskTimeTimeStats::GetCountOfTasksWithProperties(QueueId id)
128 {
129 size_t sumTaskCount = 0;
130 for (const auto &statisticsContainer : statisticsContainerPerThread_) {
131 const auto &meanStatistics = statisticsContainer[id];
132 sumTaskCount += meanStatistics.countOfTasks;
133 }
134 return sumTaskCount;
135 }
136
137 } // namespace internal
138
139 } // namespace ark::taskmanager
140