sm6375-common: power-libperfmgr: ADPF: add Early Hint feature

Add Early Hint feature and integrate with Stale Timer

Bug: 198379880
Test: build and manual test

Change-Id: I17009ee5b9ff922a79ccf5cb68be5b959038267d
This commit is contained in:
Jimmy Shiu 2024-07-18 20:16:00 +05:30 committed by Anand S
parent 362ddc9bd3
commit 938e2b96f7
No known key found for this signature in database
GPG key ID: 3B2983FA448B3D61
2 changed files with 148 additions and 54 deletions

View file

@ -145,7 +145,7 @@ PowerHintSession::PowerHintSession(int32_t tgid, int32_t uid, const std::vector<
int64_t durationNanos) { int64_t durationNanos) {
mDescriptor = new AppHintDesc(tgid, uid, threadIds); mDescriptor = new AppHintDesc(tgid, uid, threadIds);
mDescriptor->duration = std::chrono::nanoseconds(durationNanos); mDescriptor->duration = std::chrono::nanoseconds(durationNanos);
mStaleHandler = sp<StaleHandler>(new StaleHandler(this)); mHintTimerHandler = sp<HintTimerHandler>(new HintTimerHandler(this));
mPowerManagerHandler = PowerSessionManager::getInstance(); mPowerManagerHandler = PowerSessionManager::getInstance();
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
@ -154,8 +154,6 @@ PowerHintSession::PowerHintSession(int32_t tgid, int32_t uid, const std::vector<
ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count()); ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
sz = StringPrintf("adpf.%s-active", idstr.c_str()); sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), mDescriptor->is_active.load()); ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
sz = StringPrintf("adpf.%s-stale", idstr.c_str());
ATRACE_INT(sz.c_str(), isStale());
} }
PowerSessionManager::getInstance()->addPowerSession(this); PowerSessionManager::getInstance()->addPowerSession(this);
// init boost // init boost
@ -175,7 +173,7 @@ PowerHintSession::~PowerHintSession() {
sz = sz = StringPrintf("adpf.%s-active", idstr.c_str()); sz = sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), 0); ATRACE_INT(sz.c_str(), 0);
} }
mStaleHandler->setSessionDead(); mHintTimerHandler->setSessionDead();
delete mDescriptor; delete mDescriptor;
} }
@ -186,7 +184,14 @@ std::string PowerHintSession::getIdString() const {
} }
void PowerHintSession::updateUniveralBoostMode() { void PowerHintSession::updateUniveralBoostMode() {
if (ATRACE_ENABLED()) {
const std::string tag = StringPrintf("%s:updateUniveralBoostMode()", getIdString().c_str());
ATRACE_BEGIN(tag.c_str());
}
PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL); PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL);
if (ATRACE_ENABLED()) {
ATRACE_END();
}
} }
int PowerHintSession::setUclamp(int32_t min, bool update) { int PowerHintSession::setUclamp(int32_t min, bool update) {
@ -253,7 +258,7 @@ ndk::ScopedAStatus PowerHintSession::resume() {
if (mDescriptor->is_active.load()) if (mDescriptor->is_active.load())
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
mDescriptor->is_active.store(true); mDescriptor->is_active.store(true);
mStaleHandler->updateStaleTimer(); mHintTimerHandler->updateHintTimer(0);
// resume boost // resume boost
setUclamp(mDescriptor->current_min, false); setUclamp(mDescriptor->current_min, false);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
@ -332,8 +337,6 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
sz = StringPrintf("adpf.%s-hint.overtime", idstr.c_str()); sz = StringPrintf("adpf.%s-hint.overtime", idstr.c_str());
ATRACE_INT(sz.c_str(), ATRACE_INT(sz.c_str(),
actualDurations.back().durationNanos - mDescriptor->duration.count() > 0); actualDurations.back().durationNanos - mDescriptor->duration.count() > 0);
sz = StringPrintf("adpf.%s-stale", idstr.c_str());
ATRACE_INT(sz.c_str(), isStale());
} }
if (PowerHintMonitor::getInstance()->isRunning() && isStale()) { if (PowerHintMonitor::getInstance()->isRunning() && isStale()) {
@ -347,7 +350,7 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
} }
} }
mStaleHandler->updateStaleTimer(); mHintTimerHandler->updateHintTimer(actualDurations);
if (!adpfConfig->mPidOn) { if (!adpfConfig->mPidOn) {
setUclamp(adpfConfig->mUclampMinHigh); setUclamp(adpfConfig->mUclampMinHigh);
@ -357,8 +360,6 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
adpfConfig, mDescriptor->duration, actualDurations, &(mDescriptor->integral_error), adpfConfig, mDescriptor->duration, actualDurations, &(mDescriptor->integral_error),
&(mDescriptor->previous_error), getIdString()); &(mDescriptor->previous_error), getIdString());
mStaleHandler->updateStaleTimer();
/* apply to all the threads in the group */ /* apply to all the threads in the group */
if (output != 0) { if (output != 0) {
int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh), int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh),
@ -401,7 +402,7 @@ bool PowerHintSession::isActive() {
bool PowerHintSession::isStale() { bool PowerHintSession::isStale() {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
return now >= mStaleHandler->getStaleTime(); return now >= mHintTimerHandler->getStaleTime();
} }
const std::vector<int> &PowerHintSession::getTidList() const { const std::vector<int> &PowerHintSession::getTidList() const {
@ -409,70 +410,146 @@ const std::vector<int> &PowerHintSession::getTidList() const {
} }
void PowerHintSession::setStale() { void PowerHintSession::setStale() {
if (ATRACE_ENABLED()) {
const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-stale", idstr.c_str());
ATRACE_INT(sz.c_str(), 1);
}
// Reset to default uclamp value. // Reset to default uclamp value.
setUclamp(0, false); setUclamp(0, false);
// Deliver a task to check if all sessions are inactive. // Deliver a task to check if all sessions are inactive.
updateUniveralBoostMode(); updateUniveralBoostMode();
} }
void PowerHintSession::StaleHandler::updateStaleTimer() { void PowerHintSession::HintTimerHandler::updateHintTimer(int64_t actualDurationNs) {
std::lock_guard<std::mutex> guard(mStaleLock); std::lock_guard<std::mutex> guard(mStaleLock);
if (PowerHintMonitor::getInstance()->isRunning()) { std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
auto when = getStaleTime(); HintTimerState prevState = mState;
auto now = std::chrono::steady_clock::now(); mState = MONITORING;
mLastUpdatedTime.store(now); auto now = std::chrono::steady_clock::now();
if (now > when) { mLastUpdatedTime.store(now);
nanoseconds nextStartDur = nanoseconds((mSession->mDescriptor->work_period
? mSession->mDescriptor->work_period
: mSession->mDescriptor->duration.count()) -
actualDurationNs);
mNextStartTime.store(now + nextStartDur);
if (prevState != MONITORING) {
int64_t next =
static_cast<int64_t>(duration_cast<nanoseconds>(getEarlyBoostTime() - now).count());
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
next, mSession->mHintTimerHandler, NULL);
if (prevState == STALE) {
mSession->updateUniveralBoostMode(); mSession->updateUniveralBoostMode();
} }
if (!mIsMonitoringStale.load()) { }
auto next = getStaleTime(); if (ATRACE_ENABLED()) {
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleHandler); const std::string idstr = mSession->getIdString();
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed( std::string sz = StringPrintf("adpf.%s-timer.state", idstr.c_str());
duration_cast<nanoseconds>(next - now).count(), mSession->mStaleHandler, NULL); ATRACE_INT(sz.c_str(), mState);
mIsMonitoringStale.store(true); sz = StringPrintf("adpf.%s-timer.nextvsync", idstr.c_str());
} ATRACE_INT(sz.c_str(), nextStartDur.count());
if (ATRACE_ENABLED()) { sz = StringPrintf("adpf.%s-timer.nexthint", idstr.c_str());
const std::string idstr = mSession->getIdString(); ATRACE_INT(sz.c_str(),
std::string sz = StringPrintf("adpf.%s-stale", idstr.c_str()); (int64_t)(nextStartDur.count() + mSession->mDescriptor->duration.count() *
ATRACE_INT(sz.c_str(), 0); adpfConfig->mEarlyBoostTimeFactor));
}
} }
} }
time_point<steady_clock> PowerHintSession::StaleHandler::getStaleTime() { void PowerHintSession::HintTimerHandler::updateHintTimer(
const std::vector<WorkDuration> &actualDurations) {
if (actualDurations.size() == 0)
return;
if (actualDurations.size() >= 2) {
const WorkDuration &last = actualDurations[actualDurations.size() - 2];
mSession->mDescriptor->last_start = last.timeStampNanos - last.durationNanos;
ALOGD("last_start initialized by previous.");
}
const WorkDuration &current = actualDurations.back();
int64_t curr_start = current.timeStampNanos - current.durationNanos;
if (!mSession->mDescriptor->last_start) {
mSession->mDescriptor->last_start = curr_start;
ALOGD("last_start initialized by current.");
updateHintTimer(current.durationNanos);
return;
}
int64_t period = curr_start - mSession->mDescriptor->last_start;
mSession->mDescriptor->last_start = curr_start;
if (period > 0 && period < mSession->mDescriptor->duration.count() * 2) {
// Accounting workload period with moving average for the last 10 workload.
mSession->mDescriptor->work_period =
0.9 * mSession->mDescriptor->work_period + 0.1 * period;
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.period", idstr.c_str());
ATRACE_INT(sz.c_str(), period);
}
}
updateHintTimer(current.durationNanos);
}
time_point<steady_clock> PowerHintSession::HintTimerHandler::getEarlyBoostTime() {
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
if (!adpfConfig->mEarlyBoostOn) {
return getStaleTime();
}
int64_t earlyBoostTimeoutNs =
(int64_t)mSession->mDescriptor->duration.count() * adpfConfig->mEarlyBoostTimeFactor;
return mNextStartTime.load() + nanoseconds(earlyBoostTimeoutNs);
}
time_point<steady_clock> PowerHintSession::HintTimerHandler::getStaleTime() {
return mLastUpdatedTime.load() + return mLastUpdatedTime.load() +
nanoseconds(static_cast<int64_t>( nanoseconds(static_cast<int64_t>(
mSession->mDescriptor->duration.count() * mSession->mDescriptor->duration.count() *
HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor)); HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
} }
void PowerHintSession::StaleHandler::handleMessage(const Message &) { PowerHintSession::HintTimerHandler::~HintTimerHandler() {
ATRACE_CALL();
}
void PowerHintSession::HintTimerHandler::handleMessage(const Message &) {
std::lock_guard<std::mutex> guard(mStaleLock); std::lock_guard<std::mutex> guard(mStaleLock);
if (mIsSessionDead) { if (mIsSessionDead) {
return; return;
} }
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
auto when = getStaleTime(); auto staleTime = getStaleTime();
// Check if the session is stale based on the last_updated_time. auto earlyBoostTime = getEarlyBoostTime();
if (now > when) { if (adpfConfig->mEarlyBoostOn && now < earlyBoostTime) {
int64_t next =
static_cast<int64_t>(duration_cast<nanoseconds>(earlyBoostTime - now).count());
mState = MONITORING;
// Schedule for the early hint check.
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
next, mSession->mHintTimerHandler, NULL);
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.nexthint", idstr.c_str());
ATRACE_INT(sz.c_str(), next);
}
} else if (now >= staleTime) { // Check if the session is stale.
mSession->setStale(); mSession->setStale();
mIsMonitoringStale.store(false); mState = STALE;
return; } else { // Check if it's time to do early boost.
if (adpfConfig->mEarlyBoostOn) {
mState = EARLY_BOOST;
mSession->setUclamp(adpfConfig->mUclampMinHigh);
}
int64_t next = static_cast<int64_t>(duration_cast<nanoseconds>(staleTime - now).count());
// Schedule for the stale timeout check.
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
next, mSession->mHintTimerHandler, NULL);
}
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.state", idstr.c_str());
ATRACE_INT(sz.c_str(), mState);
} }
// Schedule for the next checking time.
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
duration_cast<nanoseconds>(when - now).count(), mSession->mStaleHandler, NULL);
} }
void PowerHintSession::StaleHandler::setSessionDead() { void PowerHintSession::HintTimerHandler::setSessionDead() {
std::lock_guard<std::mutex> guard(mStaleLock); std::lock_guard<std::mutex> guard(mStaleLock);
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleHandler); PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler);
mIsSessionDead = true; mIsSessionDead = true;
} }

View file

@ -52,7 +52,9 @@ struct AppHintDesc {
is_active(true), is_active(true),
update_count(0), update_count(0),
integral_error(0), integral_error(0),
previous_error(0) {} previous_error(0),
work_period(0),
last_start(0) {}
std::string toString() const; std::string toString() const;
const int32_t tgid; const int32_t tgid;
const int32_t uid; const int32_t uid;
@ -66,6 +68,9 @@ struct AppHintDesc {
uint64_t update_count; uint64_t update_count;
int64_t integral_error; int64_t integral_error;
int64_t previous_error; int64_t previous_error;
// earlyhint pace
int64_t work_period;
int64_t last_start;
}; };
class PowerHintSession : public BnPowerHintSession { class PowerHintSession : public BnPowerHintSession {
@ -85,22 +90,34 @@ class PowerHintSession : public BnPowerHintSession {
int restoreUclamp(); int restoreUclamp();
private: private:
class StaleHandler : public MessageHandler { class HintTimerHandler : public MessageHandler {
public: public:
StaleHandler(PowerHintSession *session) enum HintTimerState {
STALE,
MONITORING,
EARLY_BOOST,
};
HintTimerHandler(PowerHintSession *session)
: mSession(session), : mSession(session),
mIsMonitoringStale(false), mState(STALE),
mLastUpdatedTime(steady_clock::now()), mLastUpdatedTime(steady_clock::now()),
mIsSessionDead(false) {} mIsSessionDead(false) {}
~HintTimerHandler();
void handleMessage(const Message &message) override; void handleMessage(const Message &message) override;
void updateStaleTimer(); // Update HintTimer by actual work duration.
void updateHintTimer(int64_t actualDurationNs);
// Update HintTimer by a list of work durations which could be used for
// calculating the work period.
void updateHintTimer(const std::vector<WorkDuration> &actualDurations);
time_point<steady_clock> getEarlyBoostTime();
time_point<steady_clock> getStaleTime(); time_point<steady_clock> getStaleTime();
void setSessionDead(); void setSessionDead();
private: private:
PowerHintSession *mSession; PowerHintSession *mSession;
std::atomic<bool> mIsMonitoringStale; HintTimerState mState;
std::atomic<time_point<steady_clock>> mLastUpdatedTime; std::atomic<time_point<steady_clock>> mLastUpdatedTime;
std::atomic<time_point<steady_clock>> mNextStartTime;
std::mutex mStaleLock; std::mutex mStaleLock;
bool mIsSessionDead; bool mIsSessionDead;
}; };
@ -111,7 +128,7 @@ class PowerHintSession : public BnPowerHintSession {
int setUclamp(int32_t min, bool update = true); int setUclamp(int32_t min, bool update = true);
std::string getIdString() const; std::string getIdString() const;
AppHintDesc *mDescriptor = nullptr; AppHintDesc *mDescriptor = nullptr;
sp<StaleHandler> mStaleHandler; sp<HintTimerHandler> mHintTimerHandler;
sp<MessageHandler> mPowerManagerHandler; sp<MessageHandler> mPowerManagerHandler;
std::mutex mLock; std::mutex mLock;
std::atomic<bool> mSessionClosed = false; std::atomic<bool> mSessionClosed = false;