Home | History | Annotate | Download | only in os
      1 package com.android.internal.os;
      2 
      3 import android.os.StrictMode;
      4 import android.os.SystemClock;
      5 import android.text.TextUtils;
      6 import android.util.LongSparseLongArray;
      7 import android.util.Slog;
      8 
      9 import com.android.internal.annotations.VisibleForTesting;
     10 
     11 import java.io.BufferedReader;
     12 import java.io.FileNotFoundException;
     13 import java.io.FileReader;
     14 import java.io.IOException;
     15 
     16 /**
     17  * Reads DDR time spent at various frequencies and stores the data.  Supports diff comparison with
     18  * other KernelMemoryBandwidthStats objects. The sysfs file has the format:
     19  *
     20  * freq time_in_bucket ... time_in_bucket
     21  *      ...
     22  * freq time_in_bucket ... time_in_bucket
     23  *
     24  * where time is measured in nanoseconds.
     25  */
     26 public class KernelMemoryBandwidthStats {
     27     private static final String TAG = "KernelMemoryBandwidthStats";
     28 
     29     private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat";
     30     private static final boolean DEBUG = false;
     31 
     32     protected final LongSparseLongArray mBandwidthEntries = new LongSparseLongArray();
     33     private boolean mStatsDoNotExist = false;
     34 
     35     public void updateStats() {
     36         if (mStatsDoNotExist) {
     37             // Skip reading.
     38             return;
     39         }
     40 
     41         final long startTime = SystemClock.uptimeMillis();
     42 
     43         StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
     44         try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) {
     45             parseStats(reader);
     46         } catch (FileNotFoundException e) {
     47             Slog.w(TAG, "No kernel memory bandwidth stats available");
     48             mBandwidthEntries.clear();
     49             mStatsDoNotExist = true;
     50         } catch (IOException e) {
     51             Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage());
     52             mBandwidthEntries.clear();
     53         } finally {
     54             StrictMode.setThreadPolicy(policy);
     55         }
     56 
     57         final long readTime = SystemClock.uptimeMillis() - startTime;
     58         if (DEBUG || readTime > 100) {
     59             Slog.w(TAG, "Reading memory bandwidth file took " + readTime + "ms");
     60         }
     61     }
     62 
     63     @VisibleForTesting
     64     public void parseStats(BufferedReader reader) throws IOException {
     65         String line;
     66         TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
     67         mBandwidthEntries.clear();
     68         while ((line = reader.readLine()) != null) {
     69             splitter.setString(line);
     70             splitter.next();
     71             int bandwidth = 0;
     72             int index;
     73             do {
     74                 if ((index = mBandwidthEntries.indexOfKey(bandwidth)) >= 0) {
     75                     mBandwidthEntries.put(bandwidth, mBandwidthEntries.valueAt(index)
     76                             + Long.parseLong(splitter.next()) / 1000000);
     77                 } else {
     78                     mBandwidthEntries.put(bandwidth, Long.parseLong(splitter.next()) / 1000000);
     79                 }
     80                 if (DEBUG) {
     81                     Slog.d(TAG, String.format("bandwidth: %s time: %s", bandwidth,
     82                             mBandwidthEntries.get(bandwidth)));
     83                 }
     84                 bandwidth++;
     85             } while(splitter.hasNext());
     86         }
     87     }
     88 
     89     public LongSparseLongArray getBandwidthEntries() {
     90         return mBandwidthEntries;
     91     }
     92 }
     93