Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6f967ec authored by Adithya Srinivasan's avatar Adithya Srinivasan Committed by Automerger Merge Worker
Browse files

Merge "Limit Predictions size based on count instead of time" into sc-dev am: cc8ce71a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14413556

Change-Id: I029d163f0cef2fad066f6b5dbdeaf8ecb8a46d31
parents 35c20c7e cc8ce71a
Loading
Loading
Loading
Loading
+5 −15
Original line number Original line Diff line number Diff line
@@ -730,9 +730,11 @@ namespace impl {
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
    ATRACE_CALL();
    ATRACE_CALL();
    std::scoped_lock lock(mMutex);
    std::scoped_lock lock(mMutex);
    while (mPredictions.size() >= kMaxTokens) {
        mPredictions.erase(mPredictions.begin());
    }
    const int64_t assignedToken = mCurrentToken++;
    const int64_t assignedToken = mCurrentToken++;
    mPredictions[assignedToken] = {systemTime(), predictions};
    mPredictions[assignedToken] = predictions;
    flushTokens(systemTime());
    return assignedToken;
    return assignedToken;
}
}


@@ -740,23 +742,11 @@ std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token)
    std::scoped_lock lock(mMutex);
    std::scoped_lock lock(mMutex);
    auto predictionsIterator = mPredictions.find(token);
    auto predictionsIterator = mPredictions.find(token);
    if (predictionsIterator != mPredictions.end()) {
    if (predictionsIterator != mPredictions.end()) {
        return predictionsIterator->second.predictions;
        return predictionsIterator->second;
    }
    }
    return {};
    return {};
}
}


void TokenManager::flushTokens(nsecs_t flushTime) {
    for (auto it = mPredictions.begin(); it != mPredictions.end();) {
        if (flushTime - it->second.timestamp >= kMaxRetentionTime) {
            it = mPredictions.erase(it);
        } else {
            // Tokens are ordered by time. If i'th token is within the retention time, then the
            // i+1'th token will also be within retention time.
            break;
        }
    }
}

FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
                             JankClassificationThresholds thresholds)
                             JankClassificationThresholds thresholds)
      : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
      : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
+2 −8
Original line number Original line Diff line number Diff line
@@ -92,11 +92,6 @@ struct TimelineItem {
    bool operator!=(const TimelineItem& other) const { return !(*this == other); }
    bool operator!=(const TimelineItem& other) const { return !(*this == other); }
};
};


struct TokenManagerPrediction {
    nsecs_t timestamp = 0;
    TimelineItem predictions;
};

struct JankClassificationThresholds {
struct JankClassificationThresholds {
    // The various thresholds for App and SF. If the actual timestamp falls within the threshold
    // The various thresholds for App and SF. If the actual timestamp falls within the threshold
    // compared to prediction, we treat it as on time.
    // compared to prediction, we treat it as on time.
@@ -334,11 +329,10 @@ private:


    void flushTokens(nsecs_t flushTime) REQUIRES(mMutex);
    void flushTokens(nsecs_t flushTime) REQUIRES(mMutex);


    std::map<int64_t, TokenManagerPrediction> mPredictions GUARDED_BY(mMutex);
    std::map<int64_t, TimelineItem> mPredictions GUARDED_BY(mMutex);
    int64_t mCurrentToken GUARDED_BY(mMutex);
    int64_t mCurrentToken GUARDED_BY(mMutex);
    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
    static constexpr nsecs_t kMaxRetentionTime =
    static constexpr size_t kMaxTokens = 500;
            std::chrono::duration_cast<std::chrono::nanoseconds>(120ms).count();
};
};


class FrameTimeline : public android::frametimeline::FrameTimeline {
class FrameTimeline : public android::frametimeline::FrameTimeline {
+14 −13
Original line number Original line Diff line number Diff line
@@ -73,7 +73,7 @@ public:
        mTokenManager = &mFrameTimeline->mTokenManager;
        mTokenManager = &mFrameTimeline->mTokenManager;
        mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter;
        mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter;
        maxDisplayFrames = &mFrameTimeline->mMaxDisplayFrames;
        maxDisplayFrames = &mFrameTimeline->mMaxDisplayFrames;
        maxTokenRetentionTime = mTokenManager->kMaxRetentionTime;
        maxTokens = mTokenManager->kMaxTokens;
    }
    }


    // Each tracing session can be used for a single block of Start -> Stop.
    // Each tracing session can be used for a single block of Start -> Stop.
@@ -111,9 +111,11 @@ public:
        mFrameTimeline->setSfPresent(2500, presentFence1);
        mFrameTimeline->setSfPresent(2500, presentFence1);
    }
    }


    void flushTokens(nsecs_t flushTime) {
    void flushTokens() {
        std::lock_guard<std::mutex> lock(mTokenManager->mMutex);
        for (size_t i = 0; i < maxTokens; i++) {
        mTokenManager->flushTokens(flushTime);
            mTokenManager->generateTokenForPredictions({});
        }
        EXPECT_EQ(getPredictions().size(), maxTokens);
    }
    }


    SurfaceFrame& getSurfaceFrame(size_t displayFrameIdx, size_t surfaceFrameIdx) {
    SurfaceFrame& getSurfaceFrame(size_t displayFrameIdx, size_t surfaceFrameIdx) {
@@ -132,7 +134,7 @@ public:
                a.presentTime == b.presentTime;
                a.presentTime == b.presentTime;
    }
    }


    const std::map<int64_t, TokenManagerPrediction>& getPredictions() const {
    const std::map<int64_t, TimelineItem>& getPredictions() const {
        return mTokenManager->mPredictions;
        return mTokenManager->mPredictions;
    }
    }


@@ -155,7 +157,7 @@ public:
    TraceCookieCounter* mTraceCookieCounter;
    TraceCookieCounter* mTraceCookieCounter;
    FenceToFenceTimeMap fenceFactory;
    FenceToFenceTimeMap fenceFactory;
    uint32_t* maxDisplayFrames;
    uint32_t* maxDisplayFrames;
    nsecs_t maxTokenRetentionTime;
    size_t maxTokens;
    static constexpr pid_t kSurfaceFlingerPid = 666;
    static constexpr pid_t kSurfaceFlingerPid = 666;
    static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(2ns).count();
@@ -177,12 +179,11 @@ static constexpr int32_t sLayerIdTwo = 2;
TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
    int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
    int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
    EXPECT_EQ(getPredictions().size(), 1u);
    EXPECT_EQ(getPredictions().size(), 1u);
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();
    int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
    int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
    std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
    std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);


    // token1 should have expired
    // token1 should have expired
    EXPECT_EQ(getPredictions().size(), 1u);
    EXPECT_EQ(predictions.has_value(), false);
    EXPECT_EQ(predictions.has_value(), false);


    predictions = mTokenManager->getPredictionsForToken(token2);
    predictions = mTokenManager->getPredictionsForToken(token2);
@@ -212,7 +213,7 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {


TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
    int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
    int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();
    auto surfaceFrame =
    auto surfaceFrame =
            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
            mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
                                                       sLayerIdOne, sLayerNameOne, sLayerNameOne,
                                                       sLayerIdOne, sLayerNameOne, sLayerNameOne,
@@ -707,7 +708,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPres
                                                       sLayerNameOne, /*isBuffer*/ true);
                                                       sLayerNameOne, /*isBuffer*/ true);
    surfaceFrame1->setAcquireFenceTime(45);
    surfaceFrame1->setAcquireFenceTime(45);
    // Trigger a prediction expiry
    // Trigger a prediction expiry
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();
    mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
    mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);


    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1065,7 +1066,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_predictionExpiredDoesNotTraceExpecte
    tracingSession->StartBlocking();
    tracingSession->StartBlocking();
    int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({10, 25, 30});
    int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({10, 25, 30});
    // Flush the token so that it would expire
    // Flush the token so that it would expire
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();


    // Set up the display frame
    // Set up the display frame
    mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11));
    mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11));
@@ -1283,7 +1284,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDoesNotTraceExpecte
            mTokenManager->generateTokenForPredictions({appStartTime, appEndTime, appPresentTime});
            mTokenManager->generateTokenForPredictions({appStartTime, appEndTime, appPresentTime});


    // Flush the token so that it would expire
    // Flush the token so that it would expire
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();
    auto surfaceFrame1 =
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
                                                       sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,
                                                       sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,
@@ -1359,7 +1360,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDroppedFramesTraced
            mTokenManager->generateTokenForPredictions({appStartTime, appEndTime, appPresentTime});
            mTokenManager->generateTokenForPredictions({appStartTime, appEndTime, appPresentTime});


    // Flush the token so that it would expire
    // Flush the token so that it would expire
    flushTokens(systemTime() + maxTokenRetentionTime);
    flushTokens();
    auto surfaceFrame1 =
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
                                                       sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,
                                                       sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,