diff options
| author | 2016-03-24 15:57:01 -0700 | |
|---|---|---|
| committer | 2016-03-24 17:22:45 -0700 | |
| commit | 5ed587f25b367cfd1f68279d6cd96ee403bd6f34 (patch) | |
| tree | a3c8fdf6db6814d577fc0abed8b6c7074e4d6d28 /libs/hwui/JankTracker.cpp | |
| parent | df1e2b1457690ccbd1302078cedafbfbb8918265 (diff) | |
Track slowest frames
Fixes: 27795291
Track the 10 slowest frames over the last 24 hours
to try and give approximate insight into total system health.
Change-Id: I8aa646cef0bea185d46b3c78478266bc01d17fd7
Diffstat (limited to 'libs/hwui/JankTracker.cpp')
| -rw-r--r-- | libs/hwui/JankTracker.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index c305f65db601..2246cf9c1948 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -21,6 +21,8 @@ #include <cstdio> #include <errno.h> #include <inttypes.h> +#include <limits> +#include <cmath> #include <sys/mman.h> namespace android { @@ -202,6 +204,40 @@ void JankTracker::setFrameInterval(nsecs_t frameInterval) { } +static bool shouldReplace(SlowFrame& existing, SlowFrame& candidate) { + if (candidate.whenHours - existing.whenHours >= 24) { + // If the old slowframe is over 24 hours older than the candidate, + // replace it. It's too stale + return true; + } + if (candidate.frametimeMs > existing.frametimeMs) { + return true; + } + return false; +} + +void JankTracker::updateSlowest(const FrameInfo& frame) { + uint16_t durationMs = static_cast<uint16_t>(std::min( + ns2ms(frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::IntendedVsync]), + static_cast<nsecs_t>(std::numeric_limits<uint16_t>::max()))); + uint16_t startHours = static_cast<uint16_t>(std::lround( + ns2s(frame[FrameInfoIndex::IntendedVsync]) / 3600.0f)); + SlowFrame* toReplace = nullptr; + SlowFrame thisFrame{startHours, durationMs}; + // First find the best candidate for replacement + for (SlowFrame& existing : mData->slowestFrames) { + // If we should replace the current data with the replacement candidate, + // it means the current data is worse than the replacement candidate + if (!toReplace || shouldReplace(existing, *toReplace)) { + toReplace = &existing; + } + } + // Now see if we should replace it + if (shouldReplace(*toReplace, thisFrame)) { + *toReplace = thisFrame; + } +} + void JankTracker::addFrame(const FrameInfo& frame) { mData->totalFrameCount++; // Fast-path for jank-free frames @@ -215,6 +251,11 @@ void JankTracker::addFrame(const FrameInfo& frame) { return; } + // For slowest frames we are still interested in frames that are otherwise + // exempt (such as first-draw). Although those frames don't directly impact + // smoothness, they do impact responsiveness. + updateSlowest(frame); + if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) { return; } @@ -247,6 +288,11 @@ void JankTracker::dumpData(const ProfileData* data, int fd) { dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90)); dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95)); dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99)); + dprintf(fd, "\nSlowest frames over last 24h: "); + for (auto& slowFrame : data->slowestFrames) { + if (!slowFrame.frametimeMs) continue; + dprintf(fd, "%ums ", slowFrame.frametimeMs); + } for (int i = 0; i < NUM_BUCKETS; i++) { dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], data->jankTypeCounts[i]); } |