Commit 0fbea5c9 authored by Alexander Alekseev's avatar Alexander Alekseev Committed by Commit Bot

Ash HUD: Add latest graph values to the legend.

This CL adds latest graph values to the legend to make current
system state easier to read.

Screenshots:
https://screenshot.googleplex.com/7GEoQ34yCo4LGuX.png
https://screenshot.googleplex.com/A2jgLi6Nt8x6erc.png

Bug: 1132183
Change-Id: I4d0ac763487fe3259da22cbe84e624ddd2ef9688
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2430090Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Alexander Alekseev <alemate@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811575}
parent 9d641b5b
......@@ -4,9 +4,12 @@
#include "ash/hud_display/cpu_graph_page_view.h"
#include <algorithm>
#include <numeric>
#include "ash/hud_display/hud_constants.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/gfx/canvas.h"
namespace ash {
......@@ -41,19 +44,28 @@ CpuGraphPageView::CpuGraphPageView(const base::TimeDelta refresh_interval)
/*top=*/100, /*right=*/0, /*bottom=*/0, base::ASCIIToUTF16("s"),
base::ASCIIToUTF16("%"), data_width, 10 / refresh_interval.InSecondsF());
Legend::Formatter formatter = base::BindRepeating([](float value) {
return base::ASCIIToUTF16(base::StringPrintf(
"%d %%", std::min(100, std::max(0, (int)(value * 100)))));
});
const std::vector<Legend::Entry> legend(
{{cpu_idle_.color(), base::ASCIIToUTF16("Idle"),
base::ASCIIToUTF16("Total amount of CPU time spent\nin idle mode.")},
{cpu_user_.color(), base::ASCIIToUTF16("User"),
{{cpu_idle_, base::ASCIIToUTF16("Idle"),
base::ASCIIToUTF16("Total amount of CPU time spent\nin idle mode."),
formatter},
{cpu_user_, base::ASCIIToUTF16("User"),
base::ASCIIToUTF16(
"Total amount of CPU time spent\n running user processes.")},
{cpu_system_.color(), base::ASCIIToUTF16("System"),
"Total amount of CPU time spent\n running user processes."),
formatter},
{cpu_system_, base::ASCIIToUTF16("System"),
base::ASCIIToUTF16(
"Total amount of CPU time spent\nrunning system processes.")},
{cpu_other_.color(), base::ASCIIToUTF16("Other"),
"Total amount of CPU time spent\nrunning system processes."),
formatter},
{cpu_other_, base::ASCIIToUTF16("Other"),
base::ASCIIToUTF16(
"Total amount of CPU time spent\nrunning other tasks.\nThis "
"includes IO wait, IRQ, guest OS, etc.")}});
"includes IO wait, IRQ, guest OS, etc."),
formatter}});
CreateLegend(legend);
}
......@@ -91,10 +103,13 @@ void CpuGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
// Assume total already equals 1, no need to re-weight.
// Update graph data.
cpu_other_.AddValue(snapshot.cpu_other_part);
cpu_system_.AddValue(snapshot.cpu_system_part);
cpu_user_.AddValue(snapshot.cpu_user_part);
cpu_idle_.AddValue(snapshot.cpu_idle_part);
// unscaled values for CPU are the same. Formatter will display it as %.
cpu_other_.AddValue(snapshot.cpu_other_part, snapshot.cpu_other_part);
cpu_system_.AddValue(snapshot.cpu_system_part, snapshot.cpu_system_part);
cpu_user_.AddValue(snapshot.cpu_user_part, snapshot.cpu_user_part);
cpu_idle_.AddValue(snapshot.cpu_idle_part, snapshot.cpu_idle_part);
RefreshLegendValues();
}
} // namespace hud_display
......
......@@ -22,8 +22,9 @@ Graph::Graph(Baseline baseline, Fill fill, SkColor color)
Graph::~Graph() {}
void Graph::AddValue(float value) {
void Graph::AddValue(float value, float unscaled_value) {
data_.SaveToBuffer(value);
unscaled_data_.SaveToBuffer(unscaled_value);
}
void Graph::Layout(const gfx::Rect& graph_bounds, const Graph* base) {
......@@ -117,6 +118,28 @@ void Graph::Draw(gfx::Canvas* canvas) const {
canvas->DrawPath(path, flags);
}
float Graph::GetUnscaledValueAt(size_t index) const {
// 0 - the oldest value
// BufferSize() - 1 - the newest value.
const size_t raw_index = index < unscaled_data_.BufferSize()
? unscaled_data_.BufferSize() - 1 - index
: 0;
// It will CHECK() if index is not populated.
if (!unscaled_data_.IsFilledIndex(raw_index))
return 0;
return unscaled_data_.ReadBuffer(raw_index);
}
bool Graph::IsFilledIndex(size_t index) const {
// 0 - the oldest value
// BufferSize() - 1 - the newest value.
const size_t raw_index =
index < data_.BufferSize() ? data_.BufferSize() - 1 - index : 0;
return data_.IsFilledIndex(raw_index);
}
#if !defined(NDEBUG)
std::string Graph::DebugDump(const std::string& name) const {
std::ostringstream os;
......
......@@ -47,7 +47,8 @@ class Graph {
// |value| must be normalized to [0,1]. When graphs are drawn stacked,
// the full stack must be normalized.
void AddValue(float value);
// |unscaled_value| is used to label graph values to the user.
void AddValue(float value, float unscaled_value);
void Layout(const gfx::Rect& graph_bounds, const Graph* base);
void Draw(gfx::Canvas* canvas) const;
......@@ -57,6 +58,18 @@ class Graph {
SkColor color() const { return color_; }
// Returns value from |unscaled_data_|.
// |index| is always interpreted as "negative", i.e. "0" - current data, "1"
// - previous graph data, 2 - two steps "ago". I.e. it's number of graph
// points from the right graph edge.
float GetUnscaledValueAt(size_t index) const;
// Returns true if |data_| is populated at the given index.
// |index| is always interpreted as "negative", i.e. "0" - current data, "1"
// - previous graph data, 2 - two steps ago. I.e. it's number of graph
// points from the right graph edge.
bool IsFilledIndex(size_t index) const;
#if !defined(NDEBUG)
// Returns string representation os this object for debug.
std::string DebugDump(const std::string& name) const;
......@@ -79,6 +92,7 @@ class Graph {
std::vector<SkPoint> bottom_path_;
Data data_;
Data unscaled_data_;
};
} // namespace hud_display
......
......@@ -149,5 +149,10 @@ Grid* GraphPageViewBase::CreateGrid(float left,
horizontal_ticks_interval));
}
void GraphPageViewBase::RefreshLegendValues() {
if (legend_)
legend_->RefreshValues();
}
} // namespace hud_display
} // namespace ash
......@@ -19,6 +19,7 @@ namespace ash {
namespace hud_display {
class Grid;
class Legend;
// Interface for a single graph page.
class GraphPageViewBase : public views::View, public views::ButtonListener {
......@@ -49,6 +50,9 @@ class GraphPageViewBase : public views::View, public views::ButtonListener {
int horizontal_points_number,
int horizontal_ticks_interval);
protected:
void RefreshLegendValues();
private:
// Container for the Grid object.
views::View* grid_container_ = nullptr; // not owned
......@@ -56,7 +60,7 @@ class GraphPageViewBase : public views::View, public views::ButtonListener {
// Container for the legend object.
views::View* legend_container_ = nullptr; // not owned
views::ImageButton* legend_min_max_button_ = nullptr; // not owned
views::View* legend_ = nullptr; // not owned
Legend* legend_ = nullptr; // not owned
SEQUENCE_CHECKER(ui_sequence_checker_);
};
......
......@@ -4,6 +4,7 @@
#include "ash/hud_display/legend.h"
#include "ash/hud_display/graph.h"
#include "ash/hud_display/hud_constants.h"
#include "ash/hud_display/solid_source_background.h"
#include "cc/paint/paint_flags.h"
......@@ -35,14 +36,24 @@ class LegendEntry : public views::View {
// views::View:
void OnPaint(gfx::Canvas* canvas) override;
void SetValueIndex(size_t index);
void RefreshValue();
private:
const SkColor color_;
const Graph& graph_;
size_t value_index_ = 0;
Legend::Formatter formatter_;
views::Label* value_ = nullptr;
};
BEGIN_METADATA(LegendEntry, View)
END_METADATA
LegendEntry::LegendEntry(const Legend::Entry& data) : color_(data.color) {
LegendEntry::LegendEntry(const Legend::Entry& data)
: color_(data.graph.color()),
graph_(data.graph),
formatter_(data.formatter) {
views::BoxLayout* layout_manager =
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal));
......@@ -60,6 +71,16 @@ LegendEntry::LegendEntry(const Legend::Entry& data) : color_(data.color) {
label->SetEnabledColor(kHUDDefaultColor);
if (!data.tooltip.empty())
label->SetTooltipText(data.tooltip);
constexpr int kLabelToValueSpece = 5;
value_ = AddChildView(std::make_unique<views::Label>(
base::string16(), views::style::CONTEXT_LABEL));
layout_manager->SetFlexForView(value_, /*flex=*/1);
value_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_RIGHT);
value_->SetBorder(views::CreateEmptyBorder(0, kLabelToValueSpece, 0, 0));
value_->SetEnabledColor(kHUDDefaultColor);
ALLOW_UNUSED_LOCAL(formatter_);
}
LegendEntry::~LegendEntry() = default;
......@@ -99,8 +120,34 @@ void LegendEntry::OnPaint(gfx::Canvas* canvas) {
views::View::OnPaint(canvas);
}
void LegendEntry::SetValueIndex(size_t index) {
if (index == value_index_)
return;
value_index_ = index;
RefreshValue();
}
void LegendEntry::RefreshValue() {
if (graph_.IsFilledIndex(value_index_)) {
value_->SetText(formatter_.Run(graph_.GetUnscaledValueAt(value_index_)));
} else {
value_->SetText(base::string16());
}
}
} // namespace
Legend::Entry::Entry(const Graph& graph,
base::string16 label,
base::string16 tooltip,
Formatter formatter)
: graph(graph), label(label), tooltip(tooltip), formatter(formatter) {}
Legend::Entry::Entry(const Entry&) = default;
Legend::Entry::~Entry() = default;
BEGIN_METADATA(Legend, View)
END_METADATA
......@@ -122,5 +169,23 @@ Legend::Legend(const std::vector<Legend::Entry>& contents) {
Legend::~Legend() = default;
void Legend::SetValuesIndex(size_t index) {
for (auto* view : children()) {
if (view->GetClassName() != LegendEntry::kViewClassName)
continue;
static_cast<LegendEntry*>(view)->SetValueIndex(index);
}
}
void Legend::RefreshValues() {
for (auto* view : children()) {
if (view->GetClassName() != LegendEntry::kViewClassName)
continue;
static_cast<LegendEntry*>(view)->RefreshValue();
}
}
} // namespace hud_display
} // namespace ash
......@@ -7,21 +7,35 @@
#include <vector>
#include "base/callback.h"
#include "base/strings/string16.h"
#include "ui/views/view.h"
namespace ash {
namespace hud_display {
class Graph;
// Draws legend view.
class Legend : public views::View {
public:
using Formatter = base::RepeatingCallback<base::string16(float)>;
METADATA_HEADER(Legend);
struct Entry {
SkColor color;
Entry(const Graph& graph,
base::string16 label,
base::string16 tooltip,
Formatter formatter);
Entry(const Entry&);
~Entry();
const Graph& graph;
base::string16 label;
base::string16 tooltip;
Formatter formatter; // formatting function
};
Legend(const std::vector<Entry>& contents);
......@@ -30,6 +44,14 @@ class Legend : public views::View {
Legend& operator=(const Legend&) = delete;
~Legend() override;
// Display values for the given index. |index| is always interpreted as
// "negative", i.e. "0" - current data, "1" - previous graph data, 2 - two
// steps ago. I.e. it's number of graph points from the right graph edge.
void SetValuesIndex(size_t index);
// Update displayed values after data was updated.
void RefreshValues();
};
} // namespace hud_display
......
......@@ -4,6 +4,7 @@
#include "ash/hud_display/memory_graph_page_view.h"
#include <algorithm>
#include <numeric>
#include "ash/hud_display/grid.h"
......@@ -58,25 +59,34 @@ MemoryGraphPageView::MemoryGraphPageView(const base::TimeDelta refresh_interval)
// Hide grid until we know total memory size.
grid_->SetVisible(false);
Legend::Formatter formatter = base::BindRepeating([](float value) {
return base::ASCIIToUTF16(
base::StringPrintf("%d Mb", std::max(0, (int)(value * 1024))));
});
const std::vector<Legend::Entry> legend({
{graph_gpu_kernel_.color(), base::ASCIIToUTF16("GPU Driver"),
{graph_gpu_kernel_, base::ASCIIToUTF16("GPU Driver"),
base::ASCIIToUTF16("Kernel GPU buffers as reported\nby "
"base::SystemMemoryInfo::gem_size.")},
{graph_gpu_rss_private_.color(), base::ASCIIToUTF16("Chrome GPU"),
"base::SystemMemoryInfo::gem_size."),
formatter},
{graph_gpu_rss_private_, base::ASCIIToUTF16("Chrome GPU"),
base::ASCIIToUTF16(
"RSS private memory of\n --type=gpu-process Chrome process.")},
"RSS private memory of\n --type=gpu-process Chrome process."),
formatter},
// ARC memory is not usually visible (skipped)
{graph_renderers_rss_private_.color(),
base::ASCIIToUTF16("Chrome Renderer"),
{graph_renderers_rss_private_, base::ASCIIToUTF16("Renderers"),
base::ASCIIToUTF16(
"Sum of RSS private memory of\n--type=renderer Chrome process.")},
{graph_mem_used_unknown_.color(), base::ASCIIToUTF16("Other"),
"Sum of RSS private memory of\n--type=renderer Chrome process."),
formatter},
{graph_mem_used_unknown_, base::ASCIIToUTF16("Other"),
base::ASCIIToUTF16(
"Amount of other used memory.\nEquals to total used minus known.")},
{graph_mem_free_.color(), base::ASCIIToUTF16("Free"),
base::ASCIIToUTF16("Free memory as reported by kernel.")},
{graph_chrome_rss_private_.color(), base::ASCIIToUTF16("Browser"),
base::ASCIIToUTF16("RSS private memory of the\nmain Chrome process.")}
"Amount of other used memory.\nEquals to total used minus known."),
formatter},
{graph_mem_free_, base::ASCIIToUTF16("Free"),
base::ASCIIToUTF16("Free memory as reported by kernel."), formatter},
{graph_chrome_rss_private_, base::ASCIIToUTF16("Browser"),
base::ASCIIToUTF16("RSS private memory of the\nmain Chrome process."),
formatter}
// Browser RSS hairline skipped.
});
CreateLegend(legend);
......@@ -122,27 +132,35 @@ void MemoryGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
if (total < 1)
return;
constexpr float one_gigabyte = 1024 * 1024 * 1024;
if (total_ram_ != total) {
total_ram_ = total;
constexpr float one_gigabyte = 1024 * 1024 * 1024;
grid_->SetTopLabel(total / one_gigabyte); // In Gigabytes.
grid_->SetVisible(true);
}
const float chrome_rss_private =
(snapshot.browser_rss - snapshot.browser_rss_shared) / total;
const float mem_free = snapshot.free_ram / total;
const float chrome_rss_private_unscaled =
(snapshot.browser_rss - snapshot.browser_rss_shared);
const float chrome_rss_private = chrome_rss_private_unscaled / total;
const float mem_free_unscaled = snapshot.free_ram;
const float mem_free = mem_free_unscaled / total;
// mem_used_unknown is calculated below.
const float renderers_rss_private =
(snapshot.renderers_rss - snapshot.renderers_rss_shared) / total;
const float arc_rss_private =
(snapshot.arc_rss - snapshot.arc_rss_shared) / total;
const float gpu_rss_private =
(snapshot.gpu_rss - snapshot.gpu_rss_shared) / total;
const float gpu_kernel = snapshot.gpu_kernel / total;
const float renderers_rss_private_unscaled =
snapshot.renderers_rss - snapshot.renderers_rss_shared;
const float renderers_rss_private = renderers_rss_private_unscaled / total;
const float arc_rss_private_unscaled =
snapshot.arc_rss - snapshot.arc_rss_shared;
const float arc_rss_private = arc_rss_private_unscaled / total;
const float gpu_rss_private_unscaled =
snapshot.gpu_rss - snapshot.gpu_rss_shared;
const float gpu_rss_private = gpu_rss_private_unscaled / total;
const float gpu_kernel_unscaled = snapshot.gpu_kernel;
const float gpu_kernel = gpu_kernel_unscaled / total;
// not stacked.
const float chrome_rss_shared = snapshot.browser_rss_shared / total;
const float chrome_rss_shared_unscaled = snapshot.browser_rss_shared;
const float chrome_rss_shared = chrome_rss_shared_unscaled / total;
std::vector<float> used_buckets;
used_buckets.push_back(chrome_rss_private);
......@@ -152,22 +170,32 @@ void MemoryGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
used_buckets.push_back(gpu_rss_private);
used_buckets.push_back(gpu_kernel);
float mem_used_unknown =
const float mem_used_unknown =
1 - std::accumulate(used_buckets.begin(), used_buckets.end(), 0.0f);
const float mem_used_unknown_unscaled = mem_used_unknown * total;
if (mem_used_unknown < 0)
LOG(WARNING) << "mem_used_unknown=" << mem_used_unknown << " < 0 !";
// Update graph data.
graph_chrome_rss_private_.AddValue(chrome_rss_private);
graph_mem_free_.AddValue(mem_free);
graph_mem_used_unknown_.AddValue(std::max(mem_used_unknown, 0.0f));
graph_renderers_rss_private_.AddValue(renderers_rss_private);
graph_arc_rss_private_.AddValue(arc_rss_private);
graph_gpu_rss_private_.AddValue(gpu_rss_private);
graph_gpu_kernel_.AddValue(gpu_kernel);
graph_chrome_rss_private_.AddValue(
chrome_rss_private, chrome_rss_private_unscaled / one_gigabyte);
graph_mem_free_.AddValue(mem_free, mem_free_unscaled / one_gigabyte);
graph_mem_used_unknown_.AddValue(
std::max(mem_used_unknown, 0.0f),
std::max(mem_used_unknown_unscaled / one_gigabyte, 0.0f));
graph_renderers_rss_private_.AddValue(
renderers_rss_private, renderers_rss_private_unscaled / one_gigabyte);
graph_arc_rss_private_.AddValue(arc_rss_private,
arc_rss_private_unscaled / one_gigabyte);
graph_gpu_rss_private_.AddValue(gpu_rss_private,
gpu_rss_private_unscaled / one_gigabyte);
graph_gpu_kernel_.AddValue(gpu_kernel, gpu_kernel_unscaled / one_gigabyte);
// Not stacked.
graph_chrome_rss_shared_.AddValue(chrome_rss_shared);
graph_chrome_rss_shared_.AddValue(chrome_rss_shared,
chrome_rss_shared_unscaled / one_gigabyte);
RefreshLegendValues();
}
} // namespace hud_display
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment