1 /* 2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am.compaction; 18 19 import dalvik.annotation.optimization.NeverCompile; 20 21 import java.io.PrintWriter; 22 23 class AggregatedCompactionStats { 24 // Throttling stats 25 public long mFullCompactRequested; 26 public long mSomeCompactRequested; 27 public long mFullCompactPerformed; 28 public long mSomeCompactPerformed; 29 public long mProcCompactionsNoPidThrottled; 30 public long mProcCompactionsOomAdjThrottled; 31 public long mProcCompactionsTimeThrottled; 32 public long mProcCompactionsRSSThrottled; 33 public long mProcCompactionsMiscThrottled; 34 35 // Memory stats 36 public long mTotalDeltaAnonRssKBs; 37 public long mTotalZramConsumedKBs; 38 public long mTotalAnonMemFreedKBs; 39 public long mSumOrigAnonRss; 40 public double mMaxCompactEfficiency; 41 public double mMaxSwapEfficiency; 42 43 // Cpu time 44 public long mTotalCpuTimeMillis; 45 getThrottledSome()46 public long getThrottledSome() { return mSomeCompactRequested - mSomeCompactPerformed; } 47 getThrottledFull()48 public long getThrottledFull() { return mFullCompactRequested - mFullCompactPerformed; } 49 addMemStats(long anonRssSaved, long zramConsumed, long memFreed, long origAnonRss, long totalCpuTimeMillis)50 public void addMemStats(long anonRssSaved, long zramConsumed, long memFreed, 51 long origAnonRss, long totalCpuTimeMillis) { 52 final double compactEfficiency = memFreed / (double) origAnonRss; 53 if (compactEfficiency > mMaxCompactEfficiency) { 54 mMaxCompactEfficiency = compactEfficiency; 55 } 56 final double swapEfficiency = anonRssSaved / (double) origAnonRss; 57 if (swapEfficiency > mMaxSwapEfficiency) { 58 mMaxSwapEfficiency = swapEfficiency; 59 } 60 mTotalDeltaAnonRssKBs += anonRssSaved; 61 mTotalZramConsumedKBs += zramConsumed; 62 mTotalAnonMemFreedKBs += memFreed; 63 mSumOrigAnonRss += origAnonRss; 64 mTotalCpuTimeMillis += totalCpuTimeMillis; 65 } 66 67 @NeverCompile dump(PrintWriter pw)68 public void dump(PrintWriter pw) { 69 long totalCompactRequested = mSomeCompactRequested + mFullCompactRequested; 70 long totalCompactPerformed = mSomeCompactPerformed + mFullCompactPerformed; 71 pw.println(" Performed / Requested:"); 72 pw.println(" Some: (" + mSomeCompactPerformed + "/" + mSomeCompactRequested + ")"); 73 pw.println(" Full: (" + mFullCompactPerformed + "/" + mFullCompactRequested + ")"); 74 75 long throttledSome = getThrottledSome(); 76 long throttledFull = getThrottledFull(); 77 78 if (throttledSome > 0 || throttledFull > 0) { 79 pw.println(" Throttled:"); 80 pw.println(" Some: " + throttledSome + " Full: " + throttledFull); 81 pw.println(" Throttled by Type:"); 82 final long compactionsThrottled = totalCompactRequested - totalCompactPerformed; 83 // Any throttle that was not part of the previous categories 84 final long unaccountedThrottled = compactionsThrottled 85 - mProcCompactionsNoPidThrottled - mProcCompactionsOomAdjThrottled 86 - mProcCompactionsTimeThrottled - mProcCompactionsRSSThrottled 87 - mProcCompactionsMiscThrottled; 88 pw.println(" NoPid: " + mProcCompactionsNoPidThrottled 89 + " OomAdj: " + mProcCompactionsOomAdjThrottled + " Time: " 90 + mProcCompactionsTimeThrottled + " RSS: " + mProcCompactionsRSSThrottled 91 + " Misc: " + mProcCompactionsMiscThrottled 92 + " Unaccounted: " + unaccountedThrottled); 93 final double compactThrottlePercentage = 94 (compactionsThrottled / (double) totalCompactRequested) * 100.0; 95 pw.println(" Throttle Percentage: " + compactThrottlePercentage); 96 } 97 98 if (mFullCompactPerformed > 0) { 99 pw.println(" -----Memory Stats----"); 100 pw.println(" Total Delta Anon RSS (KB) : " + mTotalDeltaAnonRssKBs); 101 pw.println(" Total Physical ZRAM Consumed (KB): " + mTotalZramConsumedKBs); 102 // Anon Mem Freed = Delta Anon RSS - ZRAM Consumed 103 pw.println(" Total Anon Memory Freed (KB): " + mTotalAnonMemFreedKBs); 104 pw.println(" Avg Swap Efficiency (KB) (Delta Anon RSS/Orig Anon RSS): " 105 + (mTotalDeltaAnonRssKBs / (double) mSumOrigAnonRss)); 106 pw.println(" Max Swap Efficiency: " + mMaxSwapEfficiency); 107 // This tells us how much anon memory we were able to free thanks to running 108 // compaction 109 pw.println(" Avg Compaction Efficiency (Anon Freed/Anon RSS): " 110 + (mTotalAnonMemFreedKBs / (double) mSumOrigAnonRss)); 111 pw.println(" Max Compaction Efficiency: " + mMaxCompactEfficiency); 112 // This tells us how effective is the compression algorithm in physical memory 113 pw.println(" Avg Compression Ratio (1 - ZRAM Consumed/DeltaAnonRSS): " 114 + (1.0 - mTotalZramConsumedKBs / (double) mTotalDeltaAnonRssKBs)); 115 long avgKBsPerProcCompact = mFullCompactPerformed > 0 116 ? (mTotalAnonMemFreedKBs / mFullCompactPerformed) 117 : 0; 118 pw.println(" Avg Anon Mem Freed/Compaction (KB) : " + avgKBsPerProcCompact); 119 double compactionCost = 120 mTotalCpuTimeMillis / (mTotalAnonMemFreedKBs / 1024.0); // ms/MB 121 pw.println(" Compaction Cost (ms/MB): " + compactionCost); 122 } 123 } 124 } 125