• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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