1ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck/* 2ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Copyright (C) 2015 The Android Open Source Project 3ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * 4ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * you may not use this file except in compliance with the License. 6ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * You may obtain a copy of the License at 7ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * 8ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * http://www.apache.org/licenses/LICENSE-2.0 9ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * 10ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Unless required by applicable law or agreed to in writing, software 11ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * See the License for the specific language governing permissions and 14ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * limitations under the License. 15ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */ 16ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck#include "JankTracker.h" 17ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 18c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck#include "Properties.h" 19c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck 20e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck#include <algorithm> 21edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <cutils/ashmem.h> 22edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <cutils/log.h> 23ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck#include <cstdio> 24edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <errno.h> 25ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck#include <inttypes.h> 265ed587f25b367cfd1f68279d6cd96ee403bd6f34John Reck#include <limits> 275ed587f25b367cfd1f68279d6cd96ee403bd6f34John Reck#include <cmath> 28edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck#include <sys/mman.h> 29ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 30ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Recknamespace android { 31ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Recknamespace uirenderer { 32ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 33ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const char* JANK_TYPE_NAMES[] = { 34ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "Missed Vsync", 35ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "High input latency", 36ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "Slow UI thread", 37ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "Slow bitmap uploads", 38be3fba05e823f740f65b2679929347dc3dd282adJohn Reck "Slow issue draw commands", 39ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}; 40ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 41ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstruct Comparison { 42c87be99c6ead0720a8918ea38ce3b25e5c49e1c6John Reck FrameInfoIndex start; 43c87be99c6ead0720a8918ea38ce3b25e5c49e1c6John Reck FrameInfoIndex end; 44ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}; 45ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 46ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const Comparison COMPARISONS[] = { 471b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync}, 481b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync}, 491b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart}, 501b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart}, 511b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted}, 52ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}; 53ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 54ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck// If the event exceeds 10 seconds throw it away, this isn't a jank event 55ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck// it's an ANR and will be handled as such 56ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10); 57ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 58ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck/* 59660108075e61d7b7e6c138000890011510d5b079John Reck * We don't track direct-drawing via Surface:lockHardwareCanvas() 60ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * for now 61ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * 62ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * TODO: kSurfaceCanvas can negatively impact other drawing by using up 63ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * time on the RenderThread, figure out how to attribute that as a jank-causer 64ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */ 65660108075e61d7b7e6c138000890011510d5b079John Reckstatic const int64_t EXEMPT_FRAMES_FLAGS = FrameInfoFlags::SurfaceCanvas; 66ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 67edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// The bucketing algorithm controls so to speak 68edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is <= to this it goes in bucket 0 69660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kBucketMinThreshold = 5; 70edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is > this, start counting in increments of 2ms 71edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic const uint32_t kBucket2msIntervals = 32; 72edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is > this, start counting in increments of 4ms 73edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic const uint32_t kBucket4msIntervals = 48; 74edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 75c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// For testing purposes to try and eliminate test infra overhead we will 76c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// consider any unknown delay of frame start as part of the test infrastructure 77c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// and filter it out of the frame profile data 78c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reckstatic FrameInfoIndex sFrameStart = FrameInfoIndex::IntendedVsync; 79c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck 80660108075e61d7b7e6c138000890011510d5b079John Reck// The interval of the slow frame histogram 81660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kSlowFrameBucketIntervalMs = 50; 82660108075e61d7b7e6c138000890011510d5b079John Reck// The start point of the slow frame bucket in ms 83660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kSlowFrameBucketStartMs = 150; 84660108075e61d7b7e6c138000890011510d5b079John Reck 85edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// This will be called every frame, performance sensitive 86edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// Uses bit twiddling to avoid branching while achieving the packing desired 87660108075e61d7b7e6c138000890011510d5b079John Reckstatic uint32_t frameCountIndexForFrameTime(nsecs_t frameTime) { 88edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck uint32_t index = static_cast<uint32_t>(ns2ms(frameTime)); 89edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // If index > kBucketMinThreshold mask will be 0xFFFFFFFF as a result 90edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // of negating 1 (twos compliment, yaay) else mask will be 0 91edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck uint32_t mask = -(index > kBucketMinThreshold); 92edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // If index > threshold, this will essentially perform: 93edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // amountAboveThreshold = index - threshold; 94edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // index = threshold + (amountAboveThreshold / 2) 95edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // However if index is <= this will do nothing. It will underflow, do 96edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // a right shift by 0 (no-op), then overflow back to the original value 97edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals)) 98edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck + kBucket4msIntervals; 99edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals)) 100edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck + kBucket2msIntervals; 101edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // If index was < minThreshold at the start of all this it's going to 102edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // be a pretty garbage value right now. However, mask is 0 so we'll end 103edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // up with the desired result of 0. 104edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index = (index - kBucketMinThreshold) & mask; 105660108075e61d7b7e6c138000890011510d5b079John Reck return index; 106edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 107edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 108edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// Only called when dumping stats, less performance sensitive 109edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic uint32_t frameTimeForFrameCountIndex(uint32_t index) { 110edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index = index + kBucketMinThreshold; 111edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (index > kBucket2msIntervals) { 112edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index += (index - kBucket2msIntervals); 113edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 114edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (index > kBucket4msIntervals) { 115edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // This works because it was already doubled by the above if 116edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // 1 is added to shift slightly more towards the middle of the bucket 117edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck index += (index - kBucket4msIntervals) + 1; 118edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 119edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck return index; 120edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 121edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 122ba6adf66d3c44c0aa2fd8a224862ff1901d64300John ReckJankTracker::JankTracker(nsecs_t frameIntervalNanos) { 123edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // By default this will use malloc memory. It may be moved later to ashmem 124edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // if there is shared space for it and a request comes in to do that. 125edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData = new ProfileData; 126ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck reset(); 127ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck setFrameInterval(frameIntervalNanos); 128ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} 129ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 130edc524c90506d80e0fc5fb67e8de7b8f3ef53439John ReckJankTracker::~JankTracker() { 131edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck freeData(); 132edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 133edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 134edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::freeData() { 135edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (mIsMapped) { 136edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck munmap(mData, sizeof(ProfileData)); 137edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } else { 138edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck delete mData; 139edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 140edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mIsMapped = false; 141edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData = nullptr; 142edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 143edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 144edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::switchStorageToAshmem(int ashmemfd) { 145edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck int regionSize = ashmem_get_size_region(ashmemfd); 146edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (regionSize < static_cast<int>(sizeof(ProfileData))) { 147edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck ALOGW("Ashmem region is too small! Received %d, required %u", 14898fa0a322e6bf4f6b543487c820955d8598193b5John Reck regionSize, static_cast<unsigned int>(sizeof(ProfileData))); 149edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck return; 150edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 151edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck ProfileData* newData = reinterpret_cast<ProfileData*>( 152edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE, 153edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck MAP_SHARED, ashmemfd, 0)); 154edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (newData == MAP_FAILED) { 155edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck int err = errno; 156edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck ALOGW("Failed to move profile data to ashmem fd %d, error = %d", 157edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck ashmemfd, err); 158edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck return; 159edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 160edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 161edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // The new buffer may have historical data that we want to build on top of 162edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck // But let's make sure we don't overflow Just In Case 163edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck uint32_t divider = 0; 164edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (newData->totalFrameCount > (1 << 24)) { 165edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck divider = 4; 166edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 167edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck for (size_t i = 0; i < mData->jankTypeCounts.size(); i++) { 168edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->jankTypeCounts[i] >>= divider; 169edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->jankTypeCounts[i] += mData->jankTypeCounts[i]; 170edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 171edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck for (size_t i = 0; i < mData->frameCounts.size(); i++) { 172edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->frameCounts[i] >>= divider; 173edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->frameCounts[i] += mData->frameCounts[i]; 174edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 175edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->jankFrameCount >>= divider; 176edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->jankFrameCount += mData->jankFrameCount; 177edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->totalFrameCount >>= divider; 178edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck newData->totalFrameCount += mData->totalFrameCount; 179379f264bb62ace2cf2053d4765307234bf66552fJohn Reck if (newData->statStartTime > mData->statStartTime 180379f264bb62ace2cf2053d4765307234bf66552fJohn Reck || newData->statStartTime == 0) { 181379f264bb62ace2cf2053d4765307234bf66552fJohn Reck newData->statStartTime = mData->statStartTime; 182379f264bb62ace2cf2053d4765307234bf66552fJohn Reck } 183edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 184edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck freeData(); 185edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData = newData; 186edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mIsMapped = true; 187edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 188edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 189ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::setFrameInterval(nsecs_t frameInterval) { 190ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mFrameInterval = frameInterval; 191ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mThresholds[kMissedVsync] = 1; 192ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck /* 193ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Due to interpolation and sample rate differences between the touch 194ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * panel and the display (example, 85hz touch panel driving a 60hz display) 195ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * we call high latency 1.5 * frameinterval 196ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * 197ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel 198ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms 199ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Thus this must always be larger than frameInterval, or it will fail 200ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */ 201ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval); 202ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 203ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // Note that these do not add up to 1. This is intentional. It's to deal 204ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // with variance in values, and should be sort of an upper-bound on what 205ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // is reasonable to expect. 206ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval); 207ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval); 208ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval); 209ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 210ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} 211ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 212ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::addFrame(const FrameInfo& frame) { 213edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->totalFrameCount++; 214ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // Fast-path for jank-free frames 215126720aa65fd90105bdf54c04f327f146763c5cfJohn Reck int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted); 216660108075e61d7b7e6c138000890011510d5b079John Reck uint32_t framebucket = frameCountIndexForFrameTime(totalDuration); 217e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck // Keep the fast path as fast as possible. 218ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck if (CC_LIKELY(totalDuration < mFrameInterval)) { 219edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->frameCounts[framebucket]++; 220ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck return; 221ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 222ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 223660108075e61d7b7e6c138000890011510d5b079John Reck // Only things like Surface.lockHardwareCanvas() are exempt from tracking 2241b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) { 225ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck return; 226ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 227ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 228660108075e61d7b7e6c138000890011510d5b079John Reck if (framebucket <= mData->frameCounts.size()) { 229660108075e61d7b7e6c138000890011510d5b079John Reck mData->frameCounts[framebucket]++; 230660108075e61d7b7e6c138000890011510d5b079John Reck } else { 231660108075e61d7b7e6c138000890011510d5b079John Reck framebucket = (ns2ms(totalDuration) - kSlowFrameBucketStartMs) 232660108075e61d7b7e6c138000890011510d5b079John Reck / kSlowFrameBucketIntervalMs; 233660108075e61d7b7e6c138000890011510d5b079John Reck framebucket = std::min(framebucket, 234660108075e61d7b7e6c138000890011510d5b079John Reck static_cast<uint32_t>(mData->slowFrameCounts.size() - 1)); 235660108075e61d7b7e6c138000890011510d5b079John Reck framebucket = std::max(framebucket, 0u); 236660108075e61d7b7e6c138000890011510d5b079John Reck mData->slowFrameCounts[framebucket]++; 237660108075e61d7b7e6c138000890011510d5b079John Reck } 238660108075e61d7b7e6c138000890011510d5b079John Reck 239edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->jankFrameCount++; 240ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 241ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck for (int i = 0; i < NUM_BUCKETS; i++) { 242be3fba05e823f740f65b2679929347dc3dd282adJohn Reck int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end); 243ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) { 244edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->jankTypeCounts[i]++; 245ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 246ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 247ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} 248ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 249edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::dumpBuffer(const void* buffer, size_t bufsize, int fd) { 250edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck if (bufsize < sizeof(ProfileData)) { 251edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck return; 252edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck } 253edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer); 254edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dumpData(data, fd); 255edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck} 256edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck 257edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::dumpData(const ProfileData* data, int fd) { 258c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck if (sFrameStart != FrameInfoIndex::IntendedVsync) { 259c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck dprintf(fd, "\nNote: Data has been filtered!"); 260c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck } 26105f5674ae8cae94c9cc3f039e55747f0e787f959Ying Wang dprintf(fd, "\nStats since: %" PRIu64 "ns", data->statStartTime); 262edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount); 263edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount, 264edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck (float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f); 265682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck dprintf(fd, "\n50th percentile: %ums", findPercentile(data, 50)); 266edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90)); 267edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95)); 268edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99)); 269ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck for (int i = 0; i < NUM_BUCKETS; i++) { 270edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], data->jankTypeCounts[i]); 271ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 272660108075e61d7b7e6c138000890011510d5b079John Reck dprintf(fd, "\nHISTOGRAM:"); 273660108075e61d7b7e6c138000890011510d5b079John Reck for (size_t i = 0; i < data->frameCounts.size(); i++) { 274660108075e61d7b7e6c138000890011510d5b079John Reck dprintf(fd, " %ums=%u", frameTimeForFrameCountIndex(i), 275660108075e61d7b7e6c138000890011510d5b079John Reck data->frameCounts[i]); 276660108075e61d7b7e6c138000890011510d5b079John Reck } 277660108075e61d7b7e6c138000890011510d5b079John Reck for (size_t i = 0; i < data->slowFrameCounts.size(); i++) { 278660108075e61d7b7e6c138000890011510d5b079John Reck dprintf(fd, " %zums=%u", (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs, 279660108075e61d7b7e6c138000890011510d5b079John Reck data->slowFrameCounts[i]); 280660108075e61d7b7e6c138000890011510d5b079John Reck } 281edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck dprintf(fd, "\n"); 282ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} 283ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 284ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::reset() { 285edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->jankTypeCounts.fill(0); 286edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->frameCounts.fill(0); 2878f55d00c2aa351d6914dca4d0cc2c07725002d90John Reck mData->slowFrameCounts.fill(0); 288edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->totalFrameCount = 0; 289edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck mData->jankFrameCount = 0; 290379f264bb62ace2cf2053d4765307234bf66552fJohn Reck mData->statStartTime = systemTime(CLOCK_MONOTONIC); 291c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck sFrameStart = Properties::filterOutTestOverhead 292c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck ? FrameInfoIndex::HandleInputStart 293c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck : FrameInfoIndex::IntendedVsync; 294ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} 295ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 296edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckuint32_t JankTracker::findPercentile(const ProfileData* data, int percentile) { 297edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck int pos = percentile * data->totalFrameCount / 100; 298edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck int remaining = data->totalFrameCount - pos; 299660108075e61d7b7e6c138000890011510d5b079John Reck for (int i = data->slowFrameCounts.size() - 1; i >= 0; i--) { 300660108075e61d7b7e6c138000890011510d5b079John Reck remaining -= data->slowFrameCounts[i]; 301660108075e61d7b7e6c138000890011510d5b079John Reck if (remaining <= 0) { 302660108075e61d7b7e6c138000890011510d5b079John Reck return (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs; 303660108075e61d7b7e6c138000890011510d5b079John Reck } 304660108075e61d7b7e6c138000890011510d5b079John Reck } 305edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck for (int i = data->frameCounts.size() - 1; i >= 0; i--) { 306edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck remaining -= data->frameCounts[i]; 307e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck if (remaining <= 0) { 308edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck return frameTimeForFrameCountIndex(i); 309e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck } 310e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck } 311e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck return 0; 312e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck} 313e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck 314ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} /* namespace uirenderer */ 315ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} /* namespace android */ 316