memory_graph_page_view.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Copyright 2020 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 "ash/hud_display/memory_graph_page_view.h"
  5. #include <algorithm>
  6. #include <numeric>
  7. #include <string>
  8. #include "ash/hud_display/hud_constants.h"
  9. #include "ash/hud_display/reference_lines.h"
  10. #include "base/bind.h"
  11. #include "base/logging.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "ui/base/metadata/metadata_impl_macros.h"
  15. #include "ui/gfx/canvas.h"
  16. namespace ash {
  17. namespace hud_display {
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // MemoryGraphPageView, public:
  20. BEGIN_METADATA(MemoryGraphPageView, GraphPageViewBase)
  21. END_METADATA
  22. MemoryGraphPageView::MemoryGraphPageView(const base::TimeDelta refresh_interval)
  23. : graph_chrome_rss_private_(kHUDGraphWidth,
  24. Graph::Baseline::BASELINE_BOTTOM,
  25. Graph::Fill::SOLID,
  26. Graph::Style::LINES,
  27. SkColorSetA(SK_ColorRED, kHUDAlpha)),
  28. graph_mem_free_(kHUDGraphWidth,
  29. Graph::Baseline::BASELINE_BOTTOM,
  30. Graph::Fill::NONE,
  31. Graph::Style::LINES,
  32. SkColorSetA(SK_ColorDKGRAY, kHUDAlpha)),
  33. graph_mem_used_unknown_(kHUDGraphWidth,
  34. Graph::Baseline::BASELINE_BOTTOM,
  35. Graph::Fill::SOLID,
  36. Graph::Style::LINES,
  37. SkColorSetA(SK_ColorLTGRAY, kHUDAlpha)),
  38. graph_renderers_rss_private_(kHUDGraphWidth,
  39. Graph::Baseline::BASELINE_BOTTOM,
  40. Graph::Fill::SOLID,
  41. Graph::Style::LINES,
  42. SkColorSetA(SK_ColorCYAN, kHUDAlpha)),
  43. graph_arc_rss_private_(kHUDGraphWidth,
  44. Graph::Baseline::BASELINE_BOTTOM,
  45. Graph::Fill::SOLID,
  46. Graph::Style::LINES,
  47. SkColorSetA(SK_ColorMAGENTA, kHUDAlpha)),
  48. graph_gpu_rss_private_(kHUDGraphWidth,
  49. Graph::Baseline::BASELINE_BOTTOM,
  50. Graph::Fill::SOLID,
  51. Graph::Style::LINES,
  52. SkColorSetA(SK_ColorRED, kHUDAlpha)),
  53. graph_gpu_kernel_(kHUDGraphWidth,
  54. Graph::Baseline::BASELINE_BOTTOM,
  55. Graph::Fill::SOLID,
  56. Graph::Style::LINES,
  57. SkColorSetA(SK_ColorYELLOW, kHUDAlpha)),
  58. graph_chrome_rss_shared_(kHUDGraphWidth,
  59. Graph::Baseline::BASELINE_BOTTOM,
  60. Graph::Fill::NONE,
  61. Graph::Style::LINES,
  62. SkColorSetA(SK_ColorBLUE, kHUDAlpha)) {
  63. const int data_width = graph_arc_rss_private_.max_data_points();
  64. // Verical ticks are drawn every 10% (10/100 interval).
  65. constexpr float vertical_ticks_interval = 10 / 100.0;
  66. // -XX seconds on the left, 0Gb top (will be updated later), 0 seconds on the
  67. // right, 0 Gb on the bottom. Seconds and Gigabytes are dimensions. Number of
  68. // data points is data_width. horizontal tick marks are drawn every 10
  69. // seconds.
  70. reference_lines_ = CreateReferenceLines(
  71. static_cast<int>(/*left=*/-data_width * refresh_interval.InSecondsF()),
  72. /*top=*/0, /*right=*/0, /*bottom=*/0, /*x_unit=*/u"s",
  73. /*y_unit=*/u"Gb",
  74. /*horizontal_points_number=*/data_width,
  75. /*horizontal_ticks_interval=*/10 / refresh_interval.InSecondsF(),
  76. vertical_ticks_interval);
  77. // Hide reference lines until we know total memory size.
  78. reference_lines_->SetVisible(false);
  79. Legend::Formatter formatter = base::BindRepeating([](float value) {
  80. return base::ASCIIToUTF16(
  81. base::StringPrintf("%d Mb", std::max(0, (int)(value * 1024))));
  82. });
  83. const std::vector<Legend::Entry> legend({
  84. {graph_gpu_kernel_, u"GPU Driver",
  85. u"Kernel GPU buffers as reported\nby base::SystemMemoryInfo::gem_size.",
  86. formatter},
  87. {graph_gpu_rss_private_, u"Chrome GPU",
  88. u"RSS private memory of\n --type=gpu-process Chrome process.",
  89. formatter},
  90. // ARC memory is not usually visible (skipped)
  91. {graph_renderers_rss_private_, u"Renderers",
  92. u"Sum of RSS private memory of\n--type=renderer Chrome process.",
  93. formatter},
  94. {graph_mem_used_unknown_, u"Other",
  95. u"Amount of other used memory.\nEquals to total used minus known.",
  96. formatter},
  97. {graph_mem_free_, u"Free", u"Free memory as reported by kernel.",
  98. formatter},
  99. {graph_chrome_rss_private_, u"Browser",
  100. u"RSS private memory of the\nmain Chrome process.", formatter}
  101. // Browser RSS hairline skipped.
  102. });
  103. CreateLegend(legend);
  104. }
  105. MemoryGraphPageView::~MemoryGraphPageView() = default;
  106. ////////////////////////////////////////////////////////////////////////////////
  107. void MemoryGraphPageView::OnPaint(gfx::Canvas* canvas) {
  108. // TODO: Should probably update last graph point more often than shift graph.
  109. // Layout graphs.
  110. gfx::Rect rect = GetContentsBounds();
  111. // Adjust bounds to not overlap with bordering reference lines.
  112. rect.Inset(kHUDGraphReferenceLineWidth);
  113. graph_chrome_rss_private_.Layout(rect, /*base=*/nullptr);
  114. graph_mem_free_.Layout(rect, &graph_chrome_rss_private_);
  115. graph_mem_used_unknown_.Layout(rect, &graph_mem_free_);
  116. graph_renderers_rss_private_.Layout(rect, &graph_mem_used_unknown_);
  117. graph_arc_rss_private_.Layout(rect, &graph_renderers_rss_private_);
  118. graph_gpu_rss_private_.Layout(rect, &graph_arc_rss_private_);
  119. graph_gpu_kernel_.Layout(rect, &graph_gpu_rss_private_);
  120. // Not stacked.
  121. graph_chrome_rss_shared_.Layout(rect, /*base=*/nullptr);
  122. // Paint damaged area now that all parameters have been determined.
  123. graph_chrome_rss_private_.Draw(canvas);
  124. graph_mem_free_.Draw(canvas);
  125. graph_mem_used_unknown_.Draw(canvas);
  126. graph_renderers_rss_private_.Draw(canvas);
  127. graph_arc_rss_private_.Draw(canvas);
  128. graph_gpu_rss_private_.Draw(canvas);
  129. graph_gpu_kernel_.Draw(canvas);
  130. graph_chrome_rss_shared_.Draw(canvas);
  131. }
  132. void MemoryGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
  133. // TODO: Should probably update last graph point more often than shift graph.
  134. const double total = snapshot.total_ram;
  135. // Nothing to do if data is not available yet.
  136. if (total < 1)
  137. return;
  138. constexpr float one_gigabyte = 1024 * 1024 * 1024;
  139. if (total_ram_ != total) {
  140. total_ram_ = total;
  141. reference_lines_->SetTopLabel(total / one_gigabyte); // In Gigabytes.
  142. reference_lines_->SetVisible(true);
  143. }
  144. const float chrome_rss_private_unscaled =
  145. (snapshot.browser_rss - snapshot.browser_rss_shared);
  146. const float chrome_rss_private = chrome_rss_private_unscaled / total;
  147. const float mem_free_unscaled = snapshot.free_ram;
  148. const float mem_free = mem_free_unscaled / total;
  149. // mem_used_unknown is calculated below.
  150. const float renderers_rss_private_unscaled =
  151. snapshot.renderers_rss - snapshot.renderers_rss_shared;
  152. const float renderers_rss_private = renderers_rss_private_unscaled / total;
  153. const float arc_rss_private_unscaled =
  154. snapshot.arc_rss - snapshot.arc_rss_shared;
  155. const float arc_rss_private = arc_rss_private_unscaled / total;
  156. const float gpu_rss_private_unscaled =
  157. snapshot.gpu_rss - snapshot.gpu_rss_shared;
  158. const float gpu_rss_private = gpu_rss_private_unscaled / total;
  159. const float gpu_kernel_unscaled = snapshot.gpu_kernel;
  160. const float gpu_kernel = gpu_kernel_unscaled / total;
  161. // not stacked.
  162. const float chrome_rss_shared_unscaled = snapshot.browser_rss_shared;
  163. const float chrome_rss_shared = chrome_rss_shared_unscaled / total;
  164. std::vector<float> used_buckets;
  165. used_buckets.push_back(chrome_rss_private);
  166. used_buckets.push_back(mem_free);
  167. used_buckets.push_back(renderers_rss_private);
  168. used_buckets.push_back(arc_rss_private);
  169. used_buckets.push_back(gpu_rss_private);
  170. used_buckets.push_back(gpu_kernel);
  171. const float mem_used_unknown =
  172. 1 - std::accumulate(used_buckets.begin(), used_buckets.end(), 0.0f);
  173. const float mem_used_unknown_unscaled = mem_used_unknown * total;
  174. if (mem_used_unknown < 0)
  175. LOG(WARNING) << "mem_used_unknown=" << mem_used_unknown << " < 0 !";
  176. // Update graph data.
  177. graph_chrome_rss_private_.AddValue(
  178. chrome_rss_private, chrome_rss_private_unscaled / one_gigabyte);
  179. graph_mem_free_.AddValue(mem_free, mem_free_unscaled / one_gigabyte);
  180. graph_mem_used_unknown_.AddValue(
  181. std::max(mem_used_unknown, 0.0f),
  182. std::max(mem_used_unknown_unscaled / one_gigabyte, 0.0f));
  183. graph_renderers_rss_private_.AddValue(
  184. renderers_rss_private, renderers_rss_private_unscaled / one_gigabyte);
  185. graph_arc_rss_private_.AddValue(arc_rss_private,
  186. arc_rss_private_unscaled / one_gigabyte);
  187. graph_gpu_rss_private_.AddValue(gpu_rss_private,
  188. gpu_rss_private_unscaled / one_gigabyte);
  189. graph_gpu_kernel_.AddValue(gpu_kernel, gpu_kernel_unscaled / one_gigabyte);
  190. // Not stacked.
  191. graph_chrome_rss_shared_.AddValue(chrome_rss_shared,
  192. chrome_rss_shared_unscaled / one_gigabyte);
  193. RefreshLegendValues();
  194. }
  195. } // namespace hud_display
  196. } // namespace ash