1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "powerhal-adaptivecpu"
18 #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
19
20 #include "AdaptiveCpuStats.h"
21
22 #include <utils/Trace.h>
23
24 #include "AdaptiveCpu.h"
25
26 using std::chrono_literals::operator""ns;
27
28 namespace aidl {
29 namespace google {
30 namespace hardware {
31 namespace power {
32 namespace impl {
33 namespace pixel {
34
RegisterStartRun()35 void AdaptiveCpuStats::RegisterStartRun() {
36 ATRACE_CALL();
37 mNumStartedRuns++;
38 mLastRunStartTime = mTimeSource->GetTime();
39 if (mStartTime == 0ns) {
40 mStartTime = mLastRunStartTime;
41 }
42 }
43
RegisterSuccessfulRun(ThrottleDecision previousThrottleDecision,ThrottleDecision throttleDecision,WorkDurationFeatures workDurationFeatures,const AdaptiveCpuConfig & config)44 void AdaptiveCpuStats::RegisterSuccessfulRun(ThrottleDecision previousThrottleDecision,
45 ThrottleDecision throttleDecision,
46 WorkDurationFeatures workDurationFeatures,
47 const AdaptiveCpuConfig &config) {
48 ATRACE_CALL();
49 mNumSuccessfulRuns++;
50 mNumThrottles[throttleDecision]++;
51 const auto runSuccessTime = mTimeSource->GetTime();
52 mTotalRunDuration += runSuccessTime - mLastRunStartTime;
53 // Don't update previousThrottleDecision entries if we haven't run successfully before.
54 if (mLastRunSuccessTime != 0ns) {
55 mThrottleDurations[previousThrottleDecision] +=
56 std::min(runSuccessTime - mLastRunSuccessTime,
57 std::chrono::duration_cast<std::chrono::nanoseconds>(config.hintTimeout));
58 mNumDurations[previousThrottleDecision] += workDurationFeatures.numDurations;
59 mNumMissedDeadlines[previousThrottleDecision] += workDurationFeatures.numMissedDeadlines;
60 }
61 mLastRunSuccessTime = runSuccessTime;
62 }
63
DumpToStream(std::ostream & stream) const64 void AdaptiveCpuStats::DumpToStream(std::ostream &stream) const {
65 stream << "Stats:\n";
66 stream << "- Successful runs / total runs: " << mNumSuccessfulRuns << " / " << mNumStartedRuns
67 << "\n";
68 stream << "- Total run duration: " << FormatDuration(mTotalRunDuration) << "\n";
69 stream << "- Average run duration: " << FormatDuration(mTotalRunDuration / mNumSuccessfulRuns)
70 << "\n";
71 stream << "- Running time fraction: "
72 << static_cast<double>(mTotalRunDuration.count()) /
73 (mTimeSource->GetTime() - mStartTime).count()
74 << "\n";
75
76 stream << "- Number of throttles:\n";
77 size_t totalNumThrottles = 0;
78 for (const auto &[throttleDecision, numThrottles] : mNumThrottles) {
79 stream << " - " << ThrottleString(throttleDecision) << ": " << numThrottles << "\n";
80 totalNumThrottles += numThrottles;
81 }
82 stream << " - Total: " << totalNumThrottles << "\n";
83
84 stream << "- Time spent throttling:\n";
85 std::chrono::nanoseconds totalThrottleDuration;
86 for (const auto &[throttleDecision, throttleDuration] : mThrottleDurations) {
87 stream << " - " << ThrottleString(throttleDecision) << ": "
88 << FormatDuration(throttleDuration) << "\n";
89 totalThrottleDuration += throttleDuration;
90 }
91 stream << " - Total: " << FormatDuration(totalThrottleDuration) << "\n";
92
93 stream << "- Missed deadlines per throttle:\n";
94 size_t totalNumDurations = 0;
95 size_t totalNumMissedDeadlines = 0;
96 for (const auto &[throttleDecision, numDurations] : mNumDurations) {
97 const size_t numMissedDeadlines = mNumMissedDeadlines.at(throttleDecision);
98 stream << " - " << ThrottleString(throttleDecision) << ": " << numMissedDeadlines << " / "
99 << numDurations << " (" << static_cast<double>(numMissedDeadlines) / numDurations
100 << ")\n";
101 totalNumDurations += numDurations;
102 totalNumMissedDeadlines += numMissedDeadlines;
103 }
104 stream << " - Total: " << totalNumMissedDeadlines << " / " << totalNumDurations << " ("
105 << static_cast<double>(totalNumMissedDeadlines) / totalNumDurations << ")\n";
106 }
107
FormatDuration(std::chrono::nanoseconds duration)108 std::string AdaptiveCpuStats::FormatDuration(std::chrono::nanoseconds duration) {
109 double count = static_cast<double>(duration.count());
110 std::string suffix;
111 if (count < 1000.0) {
112 suffix = "ns";
113 } else if (count < 1000.0 * 1000) {
114 suffix = "us";
115 count /= 1000;
116 } else if (count < 1000.0 * 1000 * 100) {
117 suffix = "ms";
118 count /= 1000 * 1000;
119 } else {
120 suffix = "s";
121 count /= 1000 * 1000 * 1000;
122 }
123 return std::to_string(count) + suffix;
124 }
125
126 } // namespace pixel
127 } // namespace impl
128 } // namespace power
129 } // namespace hardware
130 } // namespace google
131 } // namespace aidl
132