OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 * | 63 * |
64 * <p>Known problems: | 64 * <p>Known problems: |
65 * 1. Nexus 7 devices running Kitkat have a kernel which often output an | 65 * 1. Nexus 7 devices running Kitkat have a kernel which often output an |
66 * incorrect 'idle' field in /proc/stat. The value is close to twice the | 66 * incorrect 'idle' field in /proc/stat. The value is close to twice the |
67 * correct value, and then returns to back to correct reading. Both when | 67 * correct value, and then returns to back to correct reading. Both when |
68 * jumping up and back down we might create faulty CPU load readings. | 68 * jumping up and back down we might create faulty CPU load readings. |
69 */ | 69 */ |
70 | 70 |
71 class CpuMonitor { | 71 class CpuMonitor { |
72 private static final String TAG = "CpuMonitor"; | 72 private static final String TAG = "CpuMonitor"; |
73 private static final int MOVING_AVERAGE_SAMPLES = 10; | 73 private static final int MOVING_AVERAGE_SAMPLES = 5; |
74 | 74 |
75 private static final int CPU_STAT_SAMPLE_PERIOD_MS = 1000; | 75 private static final int CPU_STAT_SAMPLE_PERIOD_MS = 2000; |
76 private static final int CPU_STAT_LOG_PERIOD_MS = 5000; | 76 private static final int CPU_STAT_LOG_PERIOD_MS = 6000; |
77 | 77 |
78 private final Context appContext; | 78 private final Context appContext; |
79 // User CPU usage at current frequency. | 79 // User CPU usage at current frequency. |
80 private final MovingAverage userCpuUsage; | 80 private final MovingAverage userCpuUsage; |
81 // System CPU usage at current frequency. | 81 // System CPU usage at current frequency. |
82 private final MovingAverage systemCpuUsage; | 82 private final MovingAverage systemCpuUsage; |
83 // Total CPU usage relative to maximum frequency. | 83 // Total CPU usage relative to maximum frequency. |
84 private final MovingAverage totalCpuUsage; | 84 private final MovingAverage totalCpuUsage; |
85 // CPU frequency in percentage from maximum. | 85 // CPU frequency in percentage from maximum. |
86 private final MovingAverage frequencyScale; | 86 private final MovingAverage frequencyScale; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 | 202 |
203 public synchronized int getCpuUsageAverage() { | 203 public synchronized int getCpuUsageAverage() { |
204 return doubleToPercent(userCpuUsage.getAverage() + systemCpuUsage.getAverage
()); | 204 return doubleToPercent(userCpuUsage.getAverage() + systemCpuUsage.getAverage
()); |
205 } | 205 } |
206 | 206 |
207 public synchronized int getFrequencyScaleAverage() { | 207 public synchronized int getFrequencyScaleAverage() { |
208 return doubleToPercent(frequencyScale.getAverage()); | 208 return doubleToPercent(frequencyScale.getAverage()); |
209 } | 209 } |
210 | 210 |
211 private void scheduleCpuUtilizationTask() { | 211 private void scheduleCpuUtilizationTask() { |
| 212 executor.cancelScheduledTasks(); |
212 executor.scheduleAtFixedRate(new Runnable() { | 213 executor.scheduleAtFixedRate(new Runnable() { |
213 @Override | 214 @Override |
214 public void run() { | 215 public void run() { |
215 cpuUtilizationTask(); | 216 cpuUtilizationTask(); |
216 } | 217 } |
217 }, CPU_STAT_SAMPLE_PERIOD_MS); | 218 }, CPU_STAT_SAMPLE_PERIOD_MS); |
218 } | 219 } |
219 | 220 |
220 private void cpuUtilizationTask() { | 221 private void cpuUtilizationTask() { |
221 boolean cpuMonitorAvailable = sampleCpuUtilization(); | 222 boolean cpuMonitorAvailable = sampleCpuUtilization(); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 return stat.toString(); | 432 return stat.toString(); |
432 } | 433 } |
433 | 434 |
434 /** | 435 /** |
435 * Read a single integer value from the named file. Return the read value | 436 * Read a single integer value from the named file. Return the read value |
436 * or if an error occurs return 0. | 437 * or if an error occurs return 0. |
437 */ | 438 */ |
438 private long readFreqFromFile(String fileName) { | 439 private long readFreqFromFile(String fileName) { |
439 long number = 0; | 440 long number = 0; |
440 try { | 441 try { |
441 FileReader fin = new FileReader(fileName); | 442 BufferedReader reader = new BufferedReader(new FileReader(fileName)); |
442 try { | 443 try { |
443 BufferedReader rdr = new BufferedReader(fin); | 444 String line = reader.readLine(); |
444 Scanner scannerC = new Scanner(rdr); | 445 number = parseLong(line); |
445 number = scannerC.nextLong(); | |
446 scannerC.close(); | |
447 } catch (Exception e) { | |
448 // CPU presumably got offline just after we opened file. | |
449 } finally { | 446 } finally { |
450 fin.close(); | 447 reader.close(); |
451 } | 448 } |
452 } catch (FileNotFoundException e) { | 449 } catch (FileNotFoundException e) { |
453 // CPU is offline, not an error. | 450 // CPU core is off, so file with its scaling frequency .../cpufreq/scaling
_cur_freq |
| 451 // is not present. This is not an error. |
454 } catch (IOException e) { | 452 } catch (IOException e) { |
455 Log.e(TAG, "Error closing file"); | 453 // CPU core is off, so file with its scaling frequency .../cpufreq/scaling
_cur_freq |
| 454 // is empty. This is not an error. |
456 } | 455 } |
457 return number; | 456 return number; |
458 } | 457 } |
| 458 |
| 459 private static long parseLong(String value) { |
| 460 long number = 0; |
| 461 try { |
| 462 number = Long.parseLong(value); |
| 463 } catch (NumberFormatException e) { |
| 464 Log.e(TAG, "parseLong error.", e); |
| 465 } |
| 466 return number; |
| 467 } |
459 | 468 |
460 /* | 469 /* |
461 * Read the current utilization of all CPUs using the cumulative first line | 470 * Read the current utilization of all CPUs using the cumulative first line |
462 * of /proc/stat. | 471 * of /proc/stat. |
463 */ | 472 */ |
464 private ProcStat readProcStat() { | 473 private ProcStat readProcStat() { |
465 long userTime = 0; | 474 long userTime = 0; |
466 long systemTime = 0; | 475 long systemTime = 0; |
467 long idleTime = 0; | 476 long idleTime = 0; |
468 try { | 477 try { |
469 FileReader fin = new FileReader("/proc/stat"); | 478 BufferedReader reader = new BufferedReader(new FileReader("/proc/stat")); |
470 try { | 479 try { |
471 BufferedReader rdr = new BufferedReader(fin); | 480 // line should contain something like this: |
472 Scanner scanner = new Scanner(rdr); | 481 // cpu 5093818 271838 3512830 165934119 101374 447076 272086 0 0 0 |
473 scanner.next(); | 482 // user nice system idle iowait irq softirq |
474 userTime = scanner.nextLong(); // user | 483 String line = reader.readLine(); |
475 long nice = scanner.nextLong(); // nice | 484 String lines[] = line.split("\\s+"); |
476 userTime += nice; | 485 int length = lines.length; |
477 systemTime = scanner.nextLong(); // system | 486 if (length >= 5) { |
478 idleTime = scanner.nextLong(); // idle | 487 userTime = parseLong(lines[1]); // user |
479 long ioWaitTime = scanner.nextLong(); // iowait | 488 userTime += parseLong(lines[2]); // nice |
480 userTime += ioWaitTime; | 489 systemTime = parseLong(lines[3]); // system |
481 long irqTime = scanner.nextLong() + scanner.nextLong(); // irq + softirq | 490 idleTime = parseLong(lines[4]); // idle |
482 systemTime += irqTime; | 491 } |
483 scanner.close(); | 492 if (length >= 8) { |
| 493 userTime += parseLong(lines[5]); // iowait |
| 494 systemTime += parseLong(lines[6]); // irq |
| 495 systemTime += parseLong(lines[7]); // softirq |
| 496 } |
484 } catch (Exception e) { | 497 } catch (Exception e) { |
485 Log.e(TAG, "Problems parsing /proc/stat"); | 498 Log.e(TAG, "Problems parsing /proc/stat", e); |
486 return null; | 499 return null; |
487 } finally { | 500 } finally { |
488 fin.close(); | 501 reader.close(); |
489 } | 502 } |
490 } catch (FileNotFoundException e) { | 503 } catch (FileNotFoundException e) { |
491 Log.e(TAG, "Cannot open /proc/stat for reading"); | 504 Log.e(TAG, "Cannot open /proc/stat for reading", e); |
492 return null; | 505 return null; |
493 } catch (IOException e) { | 506 } catch (IOException e) { |
494 Log.e(TAG, "Problems reading /proc/stat"); | 507 Log.e(TAG, "Problems reading /proc/stat", e); |
495 return null; | 508 return null; |
496 } | 509 } |
497 return new ProcStat(userTime, systemTime, idleTime); | 510 return new ProcStat(userTime, systemTime, idleTime); |
498 } | 511 } |
499 } | 512 } |
OLD | NEW |