blob: 382738e8223af71fcdaafdf4514244b05bad3527 [file] [log] [blame]
Andy Hung44d648b2022-04-08 17:33:40 -07001/*
2 * Copyright (C) 2022 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 "ThreadSnapshot"
18#include <utils/Log.h>
19#include <utils/Timers.h>
20#include <mediautils/ThreadSnapshot.h>
21
22#include <mediautils/Process.h>
23
24namespace android::mediautils {
25
26pid_t ThreadSnapshot::getTid() const {
27 std::lock_guard lg(mLock);
28 return mState.mTid;
29}
30
31void ThreadSnapshot::setTid(pid_t tid) {
32 std::lock_guard lg(mLock);
33 if (mState.mTid == tid) return;
34 mState.reset(tid);
35}
36
37void ThreadSnapshot::reset() {
38 std::lock_guard lg(mLock);
39 mState.reset(mState.mTid);
40}
41
42void ThreadSnapshot::onBegin() {
43 std::string sched = getThreadSchedAsString(getTid()); // tid could race here,
44 // accept as benign.
45 std::lock_guard lg(mLock);
46 mState.onBegin(std::move(sched));
47}
48
49void ThreadSnapshot::onEnd() {
50 std::lock_guard lg(mLock);
51 mState.onEnd();
52}
53
54std::string ThreadSnapshot::toString() const {
55 // Make a local copy of the stats data under lock.
56 State state;
57 {
58 std::lock_guard lg(mLock);
59 state = mState;
60 }
61 return state.toString();
62}
63
64void ThreadSnapshot::State::reset(pid_t tid) {
65 mTid = tid;
66 mBeginTimeNs = -2;
67 mEndTimeNs = -1;
68 mCumulativeTimeNs = 0;
69 mBeginSched.clear();
70}
71
72void ThreadSnapshot::State::onBegin(std::string sched) {
73 if (mBeginTimeNs < mEndTimeNs) {
74 mBeginTimeNs = systemTime();
75 mBeginSched = std::move(sched);
76 }
77}
78
79void ThreadSnapshot::State::onEnd() {
80 if (mEndTimeNs < mBeginTimeNs) {
81 mEndTimeNs = systemTime();
82 mCumulativeTimeNs += mEndTimeNs - mBeginTimeNs;
83 }
84}
85
86std::string ThreadSnapshot::State::toString() const {
87 if (mBeginTimeNs < 0) return {}; // never begun.
88
89 // compute time intervals.
90 const int64_t nowNs = systemTime();
91 int64_t cumulativeTimeNs = mCumulativeTimeNs;
92 int64_t diffNs = mEndTimeNs - mBeginTimeNs; // if onEnd() isn't matched, diffNs < 0.
93 if (diffNs < 0) {
94 diffNs = nowNs - mBeginTimeNs;
95 cumulativeTimeNs += diffNs;
96 }
97 // normalization for rate variables
98 const double lastRunPerSec = 1e9 / diffNs;
99 const double totalPerSec = 1e9 / cumulativeTimeNs;
100
101 // HANDLE THE SCHEDULER STATISTICS HERE
102 // current and differential statistics for the scheduler.
103 std::string schedNow = getThreadSchedAsString(mTid);
104 const auto schedMapThen = parseThreadSchedString(mBeginSched);
105 const auto schedMapNow = parseThreadSchedString(schedNow);
106 static const char * schedDiffKeyList[] = {
107 "se.sum_exec_runtime",
108 "se.nr_migrations",
109 "se.statistics.wait_sum",
110 "se.statistics.wait_count",
111 "se.statistics.iowait_sum",
112 "se.statistics.iowait_count",
113 "se.statistics.nr_forced_migrations",
114 "nr_involuntary_switches",
115 };
116
117 // compute differential rate statistics.
118 std::string diffString;
119 for (const auto diffKey : schedDiffKeyList) {
120 if (auto itThen = schedMapThen.find(diffKey);
121 itThen != schedMapThen.end()) {
122
123 if (auto itNow = schedMapNow.find(diffKey);
124 itNow != schedMapNow.end()) {
125 auto diff = itNow->second - itThen->second;
126 diff *= lastRunPerSec;
127 auto total = itNow->second * totalPerSec;
128 diffString.append(diffKey).append(" last-run:")
129 .append(std::to_string(diff))
130 .append(" cumulative:")
131 .append(std::to_string(total))
132 .append("\n");
133 }
134 }
135 }
136
137 if (!diffString.empty()) {
138 schedNow.append("*** per second stats ***\n").append(diffString);
139 }
140
141 // Return snapshot string.
142 return schedNow;
143}
144
145} // android::mediautils