146 lines
4.3 KiB
C++
146 lines
4.3 KiB
C++
/*
|
|
* Copyright (C) 2022 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "ThreadSnapshot"
|
|
#include <utils/Log.h>
|
|
#include <utils/Timers.h>
|
|
#include <mediautils/ThreadSnapshot.h>
|
|
|
|
#include <mediautils/Process.h>
|
|
|
|
namespace android::mediautils {
|
|
|
|
pid_t ThreadSnapshot::getTid() const {
|
|
std::lock_guard lg(mLock);
|
|
return mState.mTid;
|
|
}
|
|
|
|
void ThreadSnapshot::setTid(pid_t tid) {
|
|
std::lock_guard lg(mLock);
|
|
if (mState.mTid == tid) return;
|
|
mState.reset(tid);
|
|
}
|
|
|
|
void ThreadSnapshot::reset() {
|
|
std::lock_guard lg(mLock);
|
|
mState.reset(mState.mTid);
|
|
}
|
|
|
|
void ThreadSnapshot::onBegin() {
|
|
std::string sched = getThreadSchedAsString(getTid()); // tid could race here,
|
|
// accept as benign.
|
|
std::lock_guard lg(mLock);
|
|
mState.onBegin(std::move(sched));
|
|
}
|
|
|
|
void ThreadSnapshot::onEnd() {
|
|
std::lock_guard lg(mLock);
|
|
mState.onEnd();
|
|
}
|
|
|
|
std::string ThreadSnapshot::toString() const {
|
|
// Make a local copy of the stats data under lock.
|
|
State state;
|
|
{
|
|
std::lock_guard lg(mLock);
|
|
state = mState;
|
|
}
|
|
return state.toString();
|
|
}
|
|
|
|
void ThreadSnapshot::State::reset(pid_t tid) {
|
|
mTid = tid;
|
|
mBeginTimeNs = -2;
|
|
mEndTimeNs = -1;
|
|
mCumulativeTimeNs = 0;
|
|
mBeginSched.clear();
|
|
}
|
|
|
|
void ThreadSnapshot::State::onBegin(std::string sched) {
|
|
if (mBeginTimeNs < mEndTimeNs) {
|
|
mBeginTimeNs = systemTime();
|
|
mBeginSched = std::move(sched);
|
|
}
|
|
}
|
|
|
|
void ThreadSnapshot::State::onEnd() {
|
|
if (mEndTimeNs < mBeginTimeNs) {
|
|
mEndTimeNs = systemTime();
|
|
mCumulativeTimeNs += mEndTimeNs - mBeginTimeNs;
|
|
}
|
|
}
|
|
|
|
std::string ThreadSnapshot::State::toString() const {
|
|
if (mBeginTimeNs < 0) return {}; // never begun.
|
|
|
|
// compute time intervals.
|
|
const int64_t nowNs = systemTime();
|
|
int64_t cumulativeTimeNs = mCumulativeTimeNs;
|
|
int64_t diffNs = mEndTimeNs - mBeginTimeNs; // if onEnd() isn't matched, diffNs < 0.
|
|
if (diffNs < 0) {
|
|
diffNs = nowNs - mBeginTimeNs;
|
|
cumulativeTimeNs += diffNs;
|
|
}
|
|
// normalization for rate variables
|
|
const double lastRunPerSec = 1e9 / diffNs;
|
|
const double totalPerSec = 1e9 / cumulativeTimeNs;
|
|
|
|
// HANDLE THE SCHEDULER STATISTICS HERE
|
|
// current and differential statistics for the scheduler.
|
|
std::string schedNow = getThreadSchedAsString(mTid);
|
|
const auto schedMapThen = parseThreadSchedString(mBeginSched);
|
|
const auto schedMapNow = parseThreadSchedString(schedNow);
|
|
static const char * schedDiffKeyList[] = {
|
|
"se.sum_exec_runtime",
|
|
"se.nr_migrations",
|
|
"se.statistics.wait_sum",
|
|
"se.statistics.wait_count",
|
|
"se.statistics.iowait_sum",
|
|
"se.statistics.iowait_count",
|
|
"se.statistics.nr_forced_migrations",
|
|
"nr_involuntary_switches",
|
|
};
|
|
|
|
// compute differential rate statistics.
|
|
std::string diffString;
|
|
for (const auto diffKey : schedDiffKeyList) {
|
|
if (auto itThen = schedMapThen.find(diffKey);
|
|
itThen != schedMapThen.end()) {
|
|
|
|
if (auto itNow = schedMapNow.find(diffKey);
|
|
itNow != schedMapNow.end()) {
|
|
auto diff = itNow->second - itThen->second;
|
|
diff *= lastRunPerSec;
|
|
auto total = itNow->second * totalPerSec;
|
|
diffString.append(diffKey).append(" last-run:")
|
|
.append(std::to_string(diff))
|
|
.append(" cumulative:")
|
|
.append(std::to_string(total))
|
|
.append("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!diffString.empty()) {
|
|
schedNow.append("*** per second stats ***\n").append(diffString);
|
|
}
|
|
|
|
// Return snapshot string.
|
|
return schedNow;
|
|
}
|
|
|
|
} // android::mediautils
|