diff options
-rw-r--r-- | libs/hwui/JankTracker.cpp | 46 | ||||
-rw-r--r-- | libs/hwui/JankTracker.h | 8 | ||||
-rw-r--r-- | services/core/java/com/android/server/GraphicsStatsService.java | 8 |
3 files changed, 57 insertions, 5 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]); } diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h index 3887e5e65d60..1a4a4897f496 100644 --- a/libs/hwui/JankTracker.h +++ b/libs/hwui/JankTracker.h @@ -39,6 +39,11 @@ enum JankType { NUM_BUCKETS, }; +struct SlowFrame { + uint16_t whenHours; // When this occurred in CLOCK_MONOTONIC in hours + uint16_t frametimeMs; // How long the frame took in ms +}; + // Try to keep as small as possible, should match ASHMEM_SIZE in // GraphicsStatsService.java struct ProfileData { @@ -49,6 +54,8 @@ struct ProfileData { uint32_t totalFrameCount; uint32_t jankFrameCount; nsecs_t statStartTime; + + std::array<SlowFrame, 10> slowestFrames; }; // TODO: Replace DrawProfiler with this @@ -71,6 +78,7 @@ public: private: void freeData(); void setFrameInterval(nsecs_t frameIntervalNanos); + void updateSlowest(const FrameInfo& frame); static uint32_t findPercentile(const ProfileData* data, int p); static void dumpData(const ProfileData* data, int fd); diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java index 044bb04dcd7f..e29515fc36ae 100644 --- a/services/core/java/com/android/server/GraphicsStatsService.java +++ b/services/core/java/com/android/server/GraphicsStatsService.java @@ -51,17 +51,15 @@ import java.util.ArrayList; * 2) ASHMEM_SIZE (for scratch space used during dumping) * 3) ASHMEM_SIZE * HISTORY_SIZE * - * Currently ASHMEM_SIZE is 256 bytes and HISTORY_SIZE is 20. Assuming - * the system then also has 10 active rendering processes in the worst case - * this would end up using under 14KiB (12KiB for the buffers, plus some overhead - * for userId, pid, package name, and a couple other objects) + * This is currently under 16KiB total memory in the worst case of + * 20 processes in history + 10 unique active processes. * * @hide */ public class GraphicsStatsService extends IGraphicsStats.Stub { public static final String GRAPHICS_STATS_SERVICE = "graphicsstats"; private static final String TAG = "GraphicsStatsService"; - private static final int ASHMEM_SIZE = 256; + private static final int ASHMEM_SIZE = 296; private static final int HISTORY_SIZE = 20; private final Context mContext; |