Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(970)

Unified Diff: webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java

Issue 1951663002: Update CPU monitor to use moving averages. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Rename tags Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/examples/androidapp/src/org/appspot/apprtc/HudFragment.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java
diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java
index 752fd7620a1c7d420919ece00dcba6a0b916f676..2c1dffca6e0ee616d2d7e7309cd21f7a9df698b7 100644
--- a/webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java
+++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/CpuMonitor.java
@@ -14,19 +14,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
-import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;
import java.io.BufferedReader;
-import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
+import java.util.Arrays;
import java.util.Scanner;
import org.appspot.apprtc.util.LooperExecutor;
@@ -75,35 +70,34 @@ import org.appspot.apprtc.util.LooperExecutor;
class CpuMonitor {
private static final String TAG = "CpuMonitor";
- private static final String DUMP_FILE = "cpu_log.txt";
- private static final int CPU_STAT_SAMPLE_PERIOD = 2000;
- private static final int CPU_STAT_LOG_PERIOD = 6000;
+ private static final int MOVING_AVERAGE_SAMPLES = 10;
+
+ private static final int CPU_STAT_SAMPLE_PERIOD_MS = 1000;
+ private static final int CPU_STAT_LOG_PERIOD_MS = 5000;
private final Context appContext;
+ // User CPU usage at current frequency.
+ private final MovingAverage userCpuUsage;
+ // System CPU usage at current frequency.
+ private final MovingAverage systemCpuUsage;
+ // Total CPU usage relative to maximum frequency.
+ private final MovingAverage totalCpuUsage;
+ // CPU frequency in percentage from maximum.
+ private final MovingAverage frequencyScale;
+
private LooperExecutor executor;
private long lastStatLogTimeMs;
- private int iterations;
- private double currentUserCpuUsage;
- private double currentSystemCpuUsage;
- private double currentTotalCpuUsage;
- private double currentFrequencyScale = -1;
- private double sumUserCpuUsage;
- private double sumSystemCpuUsage;
- private double sumFrequencyScale;
- private double sumTotalCpuUsage;
private long[] cpuFreqMax;
private int cpusPresent;
private int actualCpusPresent;
- private boolean initialized = false;
+ private boolean initialized;
+ private boolean cpuOveruse;
private String[] maxPath;
private String[] curPath;
private double[] curFreqScales;
private ProcStat lastProcStat;
- private static boolean dumpEnabled = false;
- private static FileOutputStream fileWriter;
-
- private class ProcStat {
+ private static class ProcStat {
final long userTime;
final long systemTime;
final long idleTime;
@@ -115,10 +109,55 @@ class CpuMonitor {
}
}
+ private static class MovingAverage {
+ private final int size;
+ private double sum;
+ private double currentValue;
+ private double circBuffer[];
+ private int circBufferIndex;
+
+ public MovingAverage(int size) {
+ if (size <= 0) {
+ throw new AssertionError("Size value in MovingAverage ctor should be positive.");
+ }
+ this.size = size;
+ circBuffer = new double[size];
+ }
+
+ public void reset() {
+ Arrays.fill(circBuffer, 0);
+ circBufferIndex = 0;
+ sum = 0;
+ currentValue = 0;
+ }
+
+ public void addValue(double value) {
+ sum -= circBuffer[circBufferIndex];
+ circBuffer[circBufferIndex++] = value;
+ currentValue = value;
+ sum += value;
+ if (circBufferIndex >= size) {
+ circBufferIndex = 0;
+ }
+ }
+
+ public double getCurrent() {
+ return currentValue;
+ }
+
+ public double getAverage() {
+ return sum / (double) size;
+ }
+ }
+
public CpuMonitor(Context context) {
Log.d(TAG, "CpuMonitor ctor.");
appContext = context.getApplicationContext();
- lastStatLogTimeMs = 0;
+ userCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES);
+ systemCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES);
+ totalCpuUsage = new MovingAverage(MOVING_AVERAGE_SAMPLES);
+ frequencyScale = new MovingAverage(MOVING_AVERAGE_SAMPLES);
+ lastStatLogTimeMs = SystemClock.elapsedRealtime();
executor = new LooperExecutor();
executor.requestStart();
@@ -149,67 +188,42 @@ class CpuMonitor {
}
}
+ public synchronized void reset() {
+ if (executor != null) {
+ Log.d(TAG, "reset");
+ resetStat();
+ cpuOveruse = false;
+ }
+ }
+
public synchronized int getCpuUsageCurrent() {
- return doubleToPercent(currentTotalCpuUsage);
+ return doubleToPercent(userCpuUsage.getCurrent() + systemCpuUsage.getCurrent());
}
public synchronized int getCpuUsageAverage() {
- return sumDoubleToPercent(sumTotalCpuUsage, iterations);
+ return doubleToPercent(userCpuUsage.getAverage() + systemCpuUsage.getAverage());
}
- public synchronized int getCpuFrequencyScaleCurrent() {
- return doubleToPercent(currentFrequencyScale);
+ public synchronized int getFrequencyScaleAverage() {
+ return doubleToPercent(frequencyScale.getAverage());
}
private void scheduleCpuUtilizationTask() {
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
- logCpuUtilization();
- }
- }, CPU_STAT_SAMPLE_PERIOD);
- }
-
- private void checkDump(String statString) {
- if (!dumpEnabled) {
- return;
- }
- if (fileWriter == null) {
- Log.d(TAG, "Start log dump");
- String fileName = Environment.getExternalStorageDirectory().getAbsolutePath()
- + File.separator + DUMP_FILE;
- try {
- fileWriter = new FileOutputStream(fileName, false /* append */);
- } catch (FileNotFoundException e) {
- Log.e(TAG, "Can not open file.", e);
- dumpEnabled = false;
- return;
+ cpuUtilizationTask();
}
- }
-
- Date date = Calendar.getInstance().getTime();
- SimpleDateFormat df = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- String msg = df.format(date) + " " + TAG + ":" + statString + "\n";
- try {
- fileWriter.write(msg.getBytes());
- } catch (IOException e) {
- Log.e(TAG, "Can not write to file.", e);
- dumpEnabled = false;
- }
+ }, CPU_STAT_SAMPLE_PERIOD_MS);
}
- private void logCpuUtilization() {
- boolean logStatistics = false;
- if (SystemClock.elapsedRealtime() - lastStatLogTimeMs >= CPU_STAT_LOG_PERIOD) {
- lastStatLogTimeMs = SystemClock.elapsedRealtime();
- logStatistics = true;
- }
+ private void cpuUtilizationTask() {
boolean cpuMonitorAvailable = sampleCpuUtilization();
- if (logStatistics && cpuMonitorAvailable) {
+ if (cpuMonitorAvailable
+ && SystemClock.elapsedRealtime() - lastStatLogTimeMs >= CPU_STAT_LOG_PERIOD_MS) {
+ lastStatLogTimeMs = SystemClock.elapsedRealtime();
String statString = getStatString();
- checkDump(statString);
Log.d(TAG, statString);
- resetStat();
}
}
@@ -251,11 +265,11 @@ class CpuMonitor {
}
private synchronized void resetStat() {
- sumUserCpuUsage = 0;
- sumSystemCpuUsage = 0;
- sumFrequencyScale = 0;
- sumTotalCpuUsage = 0;
- iterations = 0;
+ userCpuUsage.reset();
+ systemCpuUsage.reset();
+ totalCpuUsage.reset();
+ frequencyScale.reset();
+ lastStatLogTimeMs = SystemClock.elapsedRealtime();
}
private int getBatteryLevel() {
@@ -305,6 +319,7 @@ class CpuMonitor {
// We have never found this CPU's max frequency. Attempt to read it.
long cpufreqMax = readFreqFromFile(maxPath[i]);
if (cpufreqMax > 0) {
+ Log.d(TAG, "Core " + i + ". Max frequency: " + cpufreqMax);
lastSeenMaxFreq = cpufreqMax;
cpuFreqMax[i] = cpufreqMax;
maxPath[i] = null; // Kill path to free its memory.
@@ -347,12 +362,9 @@ class CpuMonitor {
* incorrect only if the frequencies have peeked or dropped in between the
* invocations.
*/
- double newFrequencyScale = (double) cpuFreqCurSum / cpuFreqMaxSum;
- double frequencyScale;
- if (currentFrequencyScale > 0) {
- frequencyScale = (currentFrequencyScale + newFrequencyScale) * 0.5;
- } else {
- frequencyScale = newFrequencyScale;
+ double currentFrequencyScale = cpuFreqCurSum / (double) cpuFreqMaxSum;
+ if (frequencyScale.getCurrent() > 0) {
+ currentFrequencyScale = (frequencyScale.getCurrent() + currentFrequencyScale) * 0.5;
}
ProcStat procStat = readProcStat();
@@ -365,24 +377,23 @@ class CpuMonitor {
long diffIdleTime = procStat.idleTime - lastProcStat.idleTime;
long allTime = diffUserTime + diffSystemTime + diffIdleTime;
- if (frequencyScale == 0 || allTime == 0) {
+ if (currentFrequencyScale == 0 || allTime == 0) {
return false;
}
// Update statistics.
- currentFrequencyScale = frequencyScale;
- sumFrequencyScale += frequencyScale;
+ frequencyScale.addValue(currentFrequencyScale);
- currentUserCpuUsage = (double) diffUserTime / allTime;
- sumUserCpuUsage += currentUserCpuUsage;
+ double currentUserCpuUsage = diffUserTime / (double) allTime;
+ userCpuUsage.addValue(currentUserCpuUsage);
- currentSystemCpuUsage = (double) diffSystemTime / allTime;
- sumSystemCpuUsage += currentSystemCpuUsage;
+ double currentSystemCpuUsage = diffSystemTime / (double) allTime;
+ systemCpuUsage.addValue(currentSystemCpuUsage);
- currentTotalCpuUsage = (currentUserCpuUsage + currentSystemCpuUsage) * currentFrequencyScale;
- sumTotalCpuUsage += currentTotalCpuUsage;
+ double currentTotalCpuUsage =
+ (currentUserCpuUsage + currentSystemCpuUsage) * currentFrequencyScale;
+ totalCpuUsage.addValue(currentTotalCpuUsage);
- iterations++;
// Save new measurements for next round's deltas.
lastProcStat = procStat;
@@ -393,38 +404,30 @@ class CpuMonitor {
return (int) (d * 100 + 0.5);
}
- private int sumDoubleToPercent(double d, int iterations) {
- if (iterations > 0) {
- return (int) (d * 100.0 / (double) iterations + 0.5);
- } else {
- return 0;
- }
- }
-
- private String getStatString() {
+ private synchronized String getStatString() {
StringBuilder stat = new StringBuilder();
stat.append("CPU User: ")
- .append(doubleToPercent(currentUserCpuUsage)).append("/")
- .append(sumDoubleToPercent(sumUserCpuUsage, iterations)).append(" (")
- .append(doubleToPercent(currentUserCpuUsage * currentFrequencyScale)).append(")")
+ .append(doubleToPercent(userCpuUsage.getCurrent())).append("/")
+ .append(doubleToPercent(userCpuUsage.getAverage()))
.append(". System: ")
- .append(doubleToPercent(currentSystemCpuUsage)).append("/")
- .append(sumDoubleToPercent(sumSystemCpuUsage, iterations)).append(" (")
- .append(doubleToPercent(currentSystemCpuUsage * currentFrequencyScale)).append(")")
- .append(". CPU freq %: ")
- .append(doubleToPercent(currentFrequencyScale)).append("/")
- .append(sumDoubleToPercent(sumFrequencyScale, iterations))
- .append(". Total CPU usage: ")
- .append(doubleToPercent(currentTotalCpuUsage)).append("/")
- .append(sumDoubleToPercent(sumTotalCpuUsage, iterations))
+ .append(doubleToPercent(systemCpuUsage.getCurrent())).append("/")
+ .append(doubleToPercent(systemCpuUsage.getAverage()))
+ .append(". Freq: ")
+ .append(doubleToPercent(frequencyScale.getCurrent())).append("/")
+ .append(doubleToPercent(frequencyScale.getAverage()))
+ .append(". Total usage: ")
+ .append(doubleToPercent(totalCpuUsage.getCurrent())).append("/")
+ .append(doubleToPercent(totalCpuUsage.getAverage()))
.append(". Cores: ")
.append(actualCpusPresent);
stat.append("( ");
for (int i = 0; i < cpusPresent; i++) {
stat.append(doubleToPercent(curFreqScales[i])).append(" ");
}
- stat.append("). Battery %: ")
- .append(getBatteryLevel());
+ stat.append("). Battery: ").append(getBatteryLevel());
+ if (cpuOveruse) {
+ stat.append(". Overuse.");
+ }
return stat.toString();
}
@@ -468,13 +471,15 @@ class CpuMonitor {
BufferedReader rdr = new BufferedReader(fin);
Scanner scanner = new Scanner(rdr);
scanner.next();
- userTime = scanner.nextLong();
- long nice = scanner.nextLong();
+ userTime = scanner.nextLong(); // user
+ long nice = scanner.nextLong(); // nice
userTime += nice;
- systemTime = scanner.nextLong();
- idleTime = scanner.nextLong();
- long ioWaitTime = scanner.nextLong();
+ systemTime = scanner.nextLong(); // system
+ idleTime = scanner.nextLong(); // idle
+ long ioWaitTime = scanner.nextLong(); // iowait
userTime += ioWaitTime;
+ long irqTime = scanner.nextLong() + scanner.nextLong(); // irq + softirq
+ systemTime += irqTime;
scanner.close();
} catch (Exception e) {
Log.e(TAG, "Problems parsing /proc/stat");
« no previous file with comments | « no previous file | webrtc/examples/androidapp/src/org/appspot/apprtc/HudFragment.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698