core_times.cc 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/device/compute_pressure/core_times.h"
  5. #include "base/check_op.h"
  6. namespace device {
  7. CoreTimes::CoreTimes(const std::initializer_list<uint64_t>& times) {
  8. DCHECK_EQ(times.size(), 10u);
  9. size_t i = 0;
  10. for (auto value : times)
  11. times_[i++] = value;
  12. }
  13. void CoreTimes::set_user(uint64_t time) {
  14. if (times_[0] < time)
  15. times_[0] = time;
  16. }
  17. void CoreTimes::set_nice(uint64_t time) {
  18. if (times_[1] < time)
  19. times_[1] = time;
  20. }
  21. void CoreTimes::set_system(uint64_t time) {
  22. if (times_[2] < time)
  23. times_[2] = time;
  24. }
  25. void CoreTimes::set_idle(uint64_t time) {
  26. if (times_[3] < time)
  27. times_[3] = time;
  28. }
  29. void CoreTimes::set_iowait(uint64_t time) {
  30. if (times_[4] < time)
  31. times_[4] = time;
  32. }
  33. void CoreTimes::set_irq(uint64_t time) {
  34. if (times_[5] < time)
  35. times_[5] = time;
  36. }
  37. void CoreTimes::set_softirq(uint64_t time) {
  38. if (times_[6] < time)
  39. times_[6] = time;
  40. }
  41. void CoreTimes::set_steal(uint64_t time) {
  42. if (times_[7] < time)
  43. times_[7] = time;
  44. }
  45. void CoreTimes::set_guest(uint64_t time) {
  46. if (times_[8] < time)
  47. times_[8] = time;
  48. }
  49. void CoreTimes::set_guest_nice(uint64_t time) {
  50. if (times_[9] < time)
  51. times_[9] = time;
  52. }
  53. double CoreTimes::TimeUtilization(const CoreTimes& baseline) const {
  54. // Each of the blocks below consists of a check and a subtraction. The check
  55. // is used to bail on invalid input (/proc/stat counters should never
  56. // decrease over time).
  57. //
  58. // The check is also essential for the correctness of the subtraction -- the
  59. // result of the subtraction is stored in a temporary `uint64_t` before being
  60. // accumulated in `active_delta`, and this intermediate result must not be
  61. // negative.
  62. if (user() < baseline.user())
  63. return -1;
  64. double active_delta = user() - baseline.user();
  65. if (nice() < baseline.nice())
  66. return -1;
  67. active_delta += nice() - baseline.nice();
  68. if (system() < baseline.system())
  69. return -1;
  70. active_delta += system() - baseline.system();
  71. if (idle() < baseline.idle())
  72. return -1;
  73. uint64_t idle_delta = idle() - baseline.idle();
  74. // iowait() is unreliable, according to the Linux kernel documentation at
  75. // https://www.kernel.org/doc/Documentation/filesystems/proc.txt.
  76. if (irq() < baseline.irq())
  77. return -1;
  78. active_delta += irq() - baseline.irq();
  79. if (softirq() < baseline.softirq())
  80. return -1;
  81. active_delta += softirq() - baseline.softirq();
  82. if (steal() < baseline.steal())
  83. return -1;
  84. active_delta += steal() - baseline.steal();
  85. // guest() and guest_nice() are included in user(). Full analysis in
  86. // https://unix.stackexchange.com/a/303224/
  87. double total_delta = active_delta + idle_delta;
  88. if (total_delta == 0) {
  89. // The two snapshots represent the same point in time, so the time interval
  90. // between the two snapshots is empty.
  91. return -1;
  92. }
  93. return active_delta / total_delta;
  94. }
  95. } // namespace device