13a2260598ab8e45f1f1db9a05057532da279a541James Carrpackage com.android.internal.os; 23a2260598ab8e45f1f1db9a05057532da279a541James Carr 33a2260598ab8e45f1f1db9a05057532da279a541James Carrimport android.os.StrictMode; 43d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasaniimport android.os.SystemClock; 53a2260598ab8e45f1f1db9a05057532da279a541James Carrimport android.text.TextUtils; 63a2260598ab8e45f1f1db9a05057532da279a541James Carrimport android.util.LongSparseLongArray; 73a2260598ab8e45f1f1db9a05057532da279a541James Carrimport android.util.Slog; 83a2260598ab8e45f1f1db9a05057532da279a541James Carr 93a2260598ab8e45f1f1db9a05057532da279a541James Carrimport com.android.internal.annotations.VisibleForTesting; 103a2260598ab8e45f1f1db9a05057532da279a541James Carr 113a2260598ab8e45f1f1db9a05057532da279a541James Carrimport java.io.BufferedReader; 1261d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinskiimport java.io.FileNotFoundException; 133a2260598ab8e45f1f1db9a05057532da279a541James Carrimport java.io.FileReader; 143a2260598ab8e45f1f1db9a05057532da279a541James Carrimport java.io.IOException; 153a2260598ab8e45f1f1db9a05057532da279a541James Carr 163a2260598ab8e45f1f1db9a05057532da279a541James Carr/** 173a2260598ab8e45f1f1db9a05057532da279a541James Carr * Reads DDR time spent at various frequencies and stores the data. Supports diff comparison with 183a2260598ab8e45f1f1db9a05057532da279a541James Carr * other KernelMemoryBandwidthStats objects. The sysfs file has the format: 193a2260598ab8e45f1f1db9a05057532da279a541James Carr * 203a2260598ab8e45f1f1db9a05057532da279a541James Carr * freq time_in_bucket ... time_in_bucket 213a2260598ab8e45f1f1db9a05057532da279a541James Carr * ... 223a2260598ab8e45f1f1db9a05057532da279a541James Carr * freq time_in_bucket ... time_in_bucket 233a2260598ab8e45f1f1db9a05057532da279a541James Carr * 243a2260598ab8e45f1f1db9a05057532da279a541James Carr * where time is measured in nanoseconds. 253a2260598ab8e45f1f1db9a05057532da279a541James Carr */ 263a2260598ab8e45f1f1db9a05057532da279a541James Carrpublic class KernelMemoryBandwidthStats { 273a2260598ab8e45f1f1db9a05057532da279a541James Carr private static final String TAG = "KernelMemoryBandwidthStats"; 283a2260598ab8e45f1f1db9a05057532da279a541James Carr 293a2260598ab8e45f1f1db9a05057532da279a541James Carr private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat"; 303a2260598ab8e45f1f1db9a05057532da279a541James Carr private static final boolean DEBUG = false; 313a2260598ab8e45f1f1db9a05057532da279a541James Carr 3261d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski protected final LongSparseLongArray mBandwidthEntries = new LongSparseLongArray(); 3361d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski private boolean mStatsDoNotExist = false; 3461d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski 353a2260598ab8e45f1f1db9a05057532da279a541James Carr public void updateStats() { 3661d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski if (mStatsDoNotExist) { 3761d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski // Skip reading. 3861d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski return; 3961d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski } 4061d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski 413d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani final long startTime = SystemClock.uptimeMillis(); 423d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani 433a2260598ab8e45f1f1db9a05057532da279a541James Carr StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads(); 443a2260598ab8e45f1f1db9a05057532da279a541James Carr try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) { 453a2260598ab8e45f1f1db9a05057532da279a541James Carr parseStats(reader); 4661d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski } catch (FileNotFoundException e) { 4761d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski Slog.w(TAG, "No kernel memory bandwidth stats available"); 4861d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski mBandwidthEntries.clear(); 4961d2d372336c7e2527a06f0673a74e9b0a93ec43Adam Lesinski mStatsDoNotExist = true; 503a2260598ab8e45f1f1db9a05057532da279a541James Carr } catch (IOException e) { 513a2260598ab8e45f1f1db9a05057532da279a541James Carr Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage()); 523a2260598ab8e45f1f1db9a05057532da279a541James Carr mBandwidthEntries.clear(); 533a2260598ab8e45f1f1db9a05057532da279a541James Carr } finally { 543a2260598ab8e45f1f1db9a05057532da279a541James Carr StrictMode.setThreadPolicy(policy); 553a2260598ab8e45f1f1db9a05057532da279a541James Carr } 563d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani 573d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani final long readTime = SystemClock.uptimeMillis() - startTime; 583d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani if (DEBUG || readTime > 100) { 593d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani Slog.w(TAG, "Reading memory bandwidth file took " + readTime + "ms"); 603d5d9aefc13c95b94cfe42fe41f57c40c5f13483Amith Yamasani } 613a2260598ab8e45f1f1db9a05057532da279a541James Carr } 623a2260598ab8e45f1f1db9a05057532da279a541James Carr 633a2260598ab8e45f1f1db9a05057532da279a541James Carr @VisibleForTesting 643a2260598ab8e45f1f1db9a05057532da279a541James Carr public void parseStats(BufferedReader reader) throws IOException { 653a2260598ab8e45f1f1db9a05057532da279a541James Carr String line; 663a2260598ab8e45f1f1db9a05057532da279a541James Carr TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); 673a2260598ab8e45f1f1db9a05057532da279a541James Carr mBandwidthEntries.clear(); 683a2260598ab8e45f1f1db9a05057532da279a541James Carr while ((line = reader.readLine()) != null) { 693a2260598ab8e45f1f1db9a05057532da279a541James Carr splitter.setString(line); 703a2260598ab8e45f1f1db9a05057532da279a541James Carr splitter.next(); 713a2260598ab8e45f1f1db9a05057532da279a541James Carr int bandwidth = 0; 723a2260598ab8e45f1f1db9a05057532da279a541James Carr int index; 733a2260598ab8e45f1f1db9a05057532da279a541James Carr do { 743a2260598ab8e45f1f1db9a05057532da279a541James Carr if ((index = mBandwidthEntries.indexOfKey(bandwidth)) >= 0) { 753a2260598ab8e45f1f1db9a05057532da279a541James Carr mBandwidthEntries.put(bandwidth, mBandwidthEntries.valueAt(index) 763a2260598ab8e45f1f1db9a05057532da279a541James Carr + Long.parseLong(splitter.next()) / 1000000); 773a2260598ab8e45f1f1db9a05057532da279a541James Carr } else { 783a2260598ab8e45f1f1db9a05057532da279a541James Carr mBandwidthEntries.put(bandwidth, Long.parseLong(splitter.next()) / 1000000); 793a2260598ab8e45f1f1db9a05057532da279a541James Carr } 803a2260598ab8e45f1f1db9a05057532da279a541James Carr if (DEBUG) { 813a2260598ab8e45f1f1db9a05057532da279a541James Carr Slog.d(TAG, String.format("bandwidth: %s time: %s", bandwidth, 823a2260598ab8e45f1f1db9a05057532da279a541James Carr mBandwidthEntries.get(bandwidth))); 833a2260598ab8e45f1f1db9a05057532da279a541James Carr } 843a2260598ab8e45f1f1db9a05057532da279a541James Carr bandwidth++; 853a2260598ab8e45f1f1db9a05057532da279a541James Carr } while(splitter.hasNext()); 863a2260598ab8e45f1f1db9a05057532da279a541James Carr } 873a2260598ab8e45f1f1db9a05057532da279a541James Carr } 883a2260598ab8e45f1f1db9a05057532da279a541James Carr 893a2260598ab8e45f1f1db9a05057532da279a541James Carr public LongSparseLongArray getBandwidthEntries() { 903a2260598ab8e45f1f1db9a05057532da279a541James Carr return mBandwidthEntries; 913a2260598ab8e45f1f1db9a05057532da279a541James Carr } 923a2260598ab8e45f1f1db9a05057532da279a541James Carr} 93