diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 01cf2b94a842c..58068769e63a4 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -188,6 +188,17 @@ public abstract class PropertyInvalidatedCache { private static final boolean DEBUG = false; private static final boolean VERIFY = false; + // Per-Cache performance counters. As some cache instances are declared static, + @GuardedBy("mLock") + private long mHits = 0; + + @GuardedBy("mLock") + private long mMisses = 0; + + // Most invalidation is done in a static context, so the counters need to be accessible. + @GuardedBy("sCorkLock") + private static final HashMap sInvalidates = new HashMap<>(); + /** * If sEnabled is false then all cache operations are stubbed out. Set * it to false inside test processes. @@ -265,6 +276,7 @@ public abstract class PropertyInvalidatedCache { }; synchronized (sCorkLock) { sCaches.put(this, null); + sInvalidates.put(propertyName, (long) 0); } } @@ -365,6 +377,8 @@ public abstract class PropertyInvalidatedCache { synchronized (mLock) { if (currentNonce == mLastSeenNonce) { cachedResult = mCache.get(query); + + if (cachedResult != null) mHits++; } else { if (DEBUG) { Log.d(TAG, @@ -428,6 +442,7 @@ public abstract class PropertyInvalidatedCache { if (mLastSeenNonce == currentNonce && result != null) { mCache.put(query, result); } + mMisses++; } return maybeCheckConsistency(query, result); } @@ -531,6 +546,8 @@ public abstract class PropertyInvalidatedCache { newValueString)); } SystemProperties.set(name, newValueString); + long invalidateCount = sInvalidates.getOrDefault(name, (long) 0); + sInvalidates.put(name, ++invalidateCount); } /** @@ -758,8 +775,16 @@ public abstract class PropertyInvalidatedCache { } private void dumpContents(PrintWriter pw, String[] args) { + long invalidateCount; + + synchronized (sCorkLock) { + invalidateCount = sInvalidates.getOrDefault(mPropertyName, (long) 0); + } + synchronized (mLock) { pw.println(String.format(" Cache Property Name: %s", cacheName())); + pw.println(String.format(" Hits: %d, Misses: %d, Invalidates: %d", + mHits, mMisses, invalidateCount)); pw.println(String.format(" Last Observed Nonce: %d", mLastSeenNonce)); pw.println(String.format(" Current Size: %d, Max Size: %d", mCache.entrySet().size(), mMaxEntries));