Merge "Track slowest frames" into nyc-dev
This commit is contained in:
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user