1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ThreadSnapshot"
18*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Timers.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/ThreadSnapshot.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/Process.h>
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker namespace android::mediautils {
25*ec779b8eSAndroid Build Coastguard Worker
getTid() const26*ec779b8eSAndroid Build Coastguard Worker pid_t ThreadSnapshot::getTid() const {
27*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
28*ec779b8eSAndroid Build Coastguard Worker return mState.mTid;
29*ec779b8eSAndroid Build Coastguard Worker }
30*ec779b8eSAndroid Build Coastguard Worker
setTid(pid_t tid)31*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::setTid(pid_t tid) {
32*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
33*ec779b8eSAndroid Build Coastguard Worker if (mState.mTid == tid) return;
34*ec779b8eSAndroid Build Coastguard Worker mState.reset(tid);
35*ec779b8eSAndroid Build Coastguard Worker }
36*ec779b8eSAndroid Build Coastguard Worker
reset()37*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::reset() {
38*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
39*ec779b8eSAndroid Build Coastguard Worker mState.reset(mState.mTid);
40*ec779b8eSAndroid Build Coastguard Worker }
41*ec779b8eSAndroid Build Coastguard Worker
onBegin()42*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::onBegin() {
43*ec779b8eSAndroid Build Coastguard Worker std::string sched = getThreadSchedAsString(getTid()); // tid could race here,
44*ec779b8eSAndroid Build Coastguard Worker // accept as benign.
45*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
46*ec779b8eSAndroid Build Coastguard Worker mState.onBegin(std::move(sched));
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker
onEnd()49*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::onEnd() {
50*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
51*ec779b8eSAndroid Build Coastguard Worker mState.onEnd();
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker
toString() const54*ec779b8eSAndroid Build Coastguard Worker std::string ThreadSnapshot::toString() const {
55*ec779b8eSAndroid Build Coastguard Worker // Make a local copy of the stats data under lock.
56*ec779b8eSAndroid Build Coastguard Worker State state;
57*ec779b8eSAndroid Build Coastguard Worker {
58*ec779b8eSAndroid Build Coastguard Worker std::lock_guard lg(mLock);
59*ec779b8eSAndroid Build Coastguard Worker state = mState;
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker return state.toString();
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker
reset(pid_t tid)64*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::State::reset(pid_t tid) {
65*ec779b8eSAndroid Build Coastguard Worker mTid = tid;
66*ec779b8eSAndroid Build Coastguard Worker mBeginTimeNs = -2;
67*ec779b8eSAndroid Build Coastguard Worker mEndTimeNs = -1;
68*ec779b8eSAndroid Build Coastguard Worker mCumulativeTimeNs = 0;
69*ec779b8eSAndroid Build Coastguard Worker mBeginSched.clear();
70*ec779b8eSAndroid Build Coastguard Worker }
71*ec779b8eSAndroid Build Coastguard Worker
onBegin(std::string sched)72*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::State::onBegin(std::string sched) {
73*ec779b8eSAndroid Build Coastguard Worker if (mBeginTimeNs < mEndTimeNs) {
74*ec779b8eSAndroid Build Coastguard Worker mBeginTimeNs = systemTime();
75*ec779b8eSAndroid Build Coastguard Worker mBeginSched = std::move(sched);
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker }
78*ec779b8eSAndroid Build Coastguard Worker
onEnd()79*ec779b8eSAndroid Build Coastguard Worker void ThreadSnapshot::State::onEnd() {
80*ec779b8eSAndroid Build Coastguard Worker if (mEndTimeNs < mBeginTimeNs) {
81*ec779b8eSAndroid Build Coastguard Worker mEndTimeNs = systemTime();
82*ec779b8eSAndroid Build Coastguard Worker mCumulativeTimeNs += mEndTimeNs - mBeginTimeNs;
83*ec779b8eSAndroid Build Coastguard Worker }
84*ec779b8eSAndroid Build Coastguard Worker }
85*ec779b8eSAndroid Build Coastguard Worker
toString() const86*ec779b8eSAndroid Build Coastguard Worker std::string ThreadSnapshot::State::toString() const {
87*ec779b8eSAndroid Build Coastguard Worker if (mBeginTimeNs < 0) return {}; // never begun.
88*ec779b8eSAndroid Build Coastguard Worker
89*ec779b8eSAndroid Build Coastguard Worker // compute time intervals.
90*ec779b8eSAndroid Build Coastguard Worker const int64_t nowNs = systemTime();
91*ec779b8eSAndroid Build Coastguard Worker int64_t cumulativeTimeNs = mCumulativeTimeNs;
92*ec779b8eSAndroid Build Coastguard Worker int64_t diffNs = mEndTimeNs - mBeginTimeNs; // if onEnd() isn't matched, diffNs < 0.
93*ec779b8eSAndroid Build Coastguard Worker if (diffNs < 0) {
94*ec779b8eSAndroid Build Coastguard Worker diffNs = nowNs - mBeginTimeNs;
95*ec779b8eSAndroid Build Coastguard Worker cumulativeTimeNs += diffNs;
96*ec779b8eSAndroid Build Coastguard Worker }
97*ec779b8eSAndroid Build Coastguard Worker // normalization for rate variables
98*ec779b8eSAndroid Build Coastguard Worker const double lastRunPerSec = 1e9 / diffNs;
99*ec779b8eSAndroid Build Coastguard Worker const double totalPerSec = 1e9 / cumulativeTimeNs;
100*ec779b8eSAndroid Build Coastguard Worker
101*ec779b8eSAndroid Build Coastguard Worker // HANDLE THE SCHEDULER STATISTICS HERE
102*ec779b8eSAndroid Build Coastguard Worker // current and differential statistics for the scheduler.
103*ec779b8eSAndroid Build Coastguard Worker std::string schedNow = getThreadSchedAsString(mTid);
104*ec779b8eSAndroid Build Coastguard Worker const auto schedMapThen = parseThreadSchedString(mBeginSched);
105*ec779b8eSAndroid Build Coastguard Worker const auto schedMapNow = parseThreadSchedString(schedNow);
106*ec779b8eSAndroid Build Coastguard Worker static const char * schedDiffKeyList[] = {
107*ec779b8eSAndroid Build Coastguard Worker "se.sum_exec_runtime",
108*ec779b8eSAndroid Build Coastguard Worker "se.nr_migrations",
109*ec779b8eSAndroid Build Coastguard Worker "se.statistics.wait_sum",
110*ec779b8eSAndroid Build Coastguard Worker "se.statistics.wait_count",
111*ec779b8eSAndroid Build Coastguard Worker "se.statistics.iowait_sum",
112*ec779b8eSAndroid Build Coastguard Worker "se.statistics.iowait_count",
113*ec779b8eSAndroid Build Coastguard Worker "se.statistics.nr_forced_migrations",
114*ec779b8eSAndroid Build Coastguard Worker "nr_involuntary_switches",
115*ec779b8eSAndroid Build Coastguard Worker };
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker // compute differential rate statistics.
118*ec779b8eSAndroid Build Coastguard Worker std::string diffString;
119*ec779b8eSAndroid Build Coastguard Worker for (const auto diffKey : schedDiffKeyList) {
120*ec779b8eSAndroid Build Coastguard Worker if (auto itThen = schedMapThen.find(diffKey);
121*ec779b8eSAndroid Build Coastguard Worker itThen != schedMapThen.end()) {
122*ec779b8eSAndroid Build Coastguard Worker
123*ec779b8eSAndroid Build Coastguard Worker if (auto itNow = schedMapNow.find(diffKey);
124*ec779b8eSAndroid Build Coastguard Worker itNow != schedMapNow.end()) {
125*ec779b8eSAndroid Build Coastguard Worker auto diff = itNow->second - itThen->second;
126*ec779b8eSAndroid Build Coastguard Worker diff *= lastRunPerSec;
127*ec779b8eSAndroid Build Coastguard Worker auto total = itNow->second * totalPerSec;
128*ec779b8eSAndroid Build Coastguard Worker diffString.append(diffKey).append(" last-run:")
129*ec779b8eSAndroid Build Coastguard Worker .append(std::to_string(diff))
130*ec779b8eSAndroid Build Coastguard Worker .append(" cumulative:")
131*ec779b8eSAndroid Build Coastguard Worker .append(std::to_string(total))
132*ec779b8eSAndroid Build Coastguard Worker .append("\n");
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker }
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker
137*ec779b8eSAndroid Build Coastguard Worker if (!diffString.empty()) {
138*ec779b8eSAndroid Build Coastguard Worker schedNow.append("*** per second stats ***\n").append(diffString);
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker // Return snapshot string.
142*ec779b8eSAndroid Build Coastguard Worker return schedNow;
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker
145*ec779b8eSAndroid Build Coastguard Worker } // android::mediautils
146