Skip to content

Commit

Permalink
Update MemoryTrack with stacked graph
Browse files Browse the repository at this point in the history
With this change, we update the `MemoryTrack` to inherit from the new
`GraphTrack`, and draw data series as a stacked graph.
  • Loading branch information
vickyliu-go4it committed Jun 11, 2021
1 parent e3a20d1 commit a15ed0d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 116 deletions.
99 changes: 26 additions & 73 deletions src/OrbitGl/MemoryTrack.cpp
Expand Up @@ -10,91 +10,44 @@

namespace orbit_gl {

void MemoryTrack::Draw(Batcher& batcher, TextRenderer& text_renderer,
uint64_t current_mouse_time_ns, PickingMode picking_mode, float z_offset) {
VariableTrack::Draw(batcher, text_renderer, current_mouse_time_ns, picking_mode, z_offset);

if (values_.empty() || picking_mode != PickingMode::kNone) return;

float text_z = GlCanvas::kZValueTrackText + z_offset;
uint32_t font_size = layout_->CalculateZoomedFontSize();

float content_height =
(size_[1] - layout_->GetTrackTabHeight() - layout_->GetTrackBottomMargin());
Vec2 content_pos = pos_;
content_pos[1] -= layout_->GetTrackTabHeight();

// Add warning threshold text box and line.
if (warning_threshold_.has_value()) {
const Color kThresholdColor(244, 67, 54, 255);
double normalized_value = (warning_threshold_.value().second - min_) * inv_value_range_;
float x = pos_[0];
float y =
content_pos[1] - content_height + static_cast<float>(normalized_value) * content_height;
Vec2 from(x, y);
Vec2 to(x + size_[0], y);

std::string text = warning_threshold_.value().first;
float string_width = text_renderer.GetStringWidth(text.c_str(), font_size);
Vec2 text_box_size(string_width, layout_->GetTextBoxHeight());
Vec2 text_box_position(pos_[0] + layout_->GetRightMargin(),
y - layout_->GetTextBoxHeight() / 2.f);
text_renderer.AddText(text.c_str(), text_box_position[0],
text_box_position[1] + layout_->GetTextOffset(), text_z, kThresholdColor,
font_size, text_box_size[0]);

batcher.AddLine(from, from + Vec2(layout_->GetRightMargin() / 2.f, 0), text_z, kThresholdColor);
batcher.AddLine(Vec2(text_box_position[0] + text_box_size[0], y), to, text_z, kThresholdColor);
}

// Add value upper bound text box (e.g., the "System Memory Total" text box for memory tracks).
const Color kWhite(255, 255, 255, 255);
if (value_upper_bound_.has_value()) {
std::string text = value_upper_bound_.value().first;
float string_width = text_renderer.GetStringWidth(text.c_str(), font_size);
Vec2 text_box_size(string_width, layout_->GetTextBoxHeight());
Vec2 text_box_position(pos_[0] + size_[0] - text_box_size[0] - layout_->GetRightMargin() -
layout_->GetSliderWidth(),
content_pos[1] - layout_->GetTextBoxHeight() / 2.f);
text_renderer.AddText(text.c_str(), text_box_position[0],
text_box_position[1] + layout_->GetTextOffset(), text_z, kWhite,
font_size, text_box_size[0]);
}

// Add value lower bound text box.
if (value_lower_bound_.has_value()) {
std::string text = value_lower_bound_.value().first;
float string_width = text_renderer.GetStringWidth(text.c_str(), font_size);
Vec2 text_box_size(string_width, layout_->GetTextBoxHeight());
Vec2 text_box_position(pos_[0] + size_[0] - text_box_size[0] - layout_->GetRightMargin() -
layout_->GetSliderWidth(),
content_pos[1] - content_height);
text_renderer.AddText(text.c_str(), text_box_position[0],
text_box_position[1] + layout_->GetTextOffset(), text_z, kWhite,
font_size, text_box_size[0]);
}
template <std::size_t Size>
void MemoryTrack<Size>::Draw(Batcher& batcher, TextRenderer& text_renderer,
uint64_t current_mouse_time_ns, PickingMode picking_mode,
float z_offset) {
GraphTrack::Draw(batcher, text_renderer, current_mouse_time_ns, picking_mode, z_offset);
AnnotationTrack::DrawAnnotation(batcher, text_renderer, picking_mode,
GlCanvas::kZValueTrackText + z_offset);
}

void MemoryTrack::SetWarningThresholdWhenEmpty(const std::string& pretty_label, double raw_value) {
if (warning_threshold_.has_value()) return;
warning_threshold_ = std::make_pair(pretty_label, raw_value);
template <std::size_t Size>
void MemoryTrack<Size>::SetWarningThresholdWhenEmpty(const std::string& pretty_label,
double raw_value) {
AnnotationTrack::SetWarningThresholdWhenEmpty(pretty_label, raw_value);
UpdateMinAndMax(raw_value);
}

void MemoryTrack::SetValueUpperBoundWhenEmpty(const std::string& pretty_label, double raw_value) {
if (value_upper_bound_.has_value()) return;
value_upper_bound_ = std::make_pair(pretty_label, raw_value);
template <std::size_t Size>
void MemoryTrack<Size>::SetValueUpperBoundWhenEmpty(const std::string& pretty_label,
double raw_value) {
AnnotationTrack::SetValueUpperBoundWhenEmpty(pretty_label, raw_value);
UpdateMinAndMax(raw_value);
}
void MemoryTrack::SetValueLowerBoundWhenEmpty(const std::string& pretty_label, double raw_value) {
if (value_lower_bound_.has_value()) return;
value_lower_bound_ = std::make_pair(pretty_label, raw_value);

template <std::size_t Size>
void MemoryTrack<Size>::SetValueLowerBoundWhenEmpty(const std::string& pretty_label,
double raw_value) {
AnnotationTrack::SetValueLowerBoundWhenEmpty(pretty_label, raw_value);
UpdateMinAndMax(raw_value);
}

void MemoryTrack::UpdateMinAndMax(double value) {
template <std::size_t Size>
void MemoryTrack<Size>::UpdateMinAndMax(double value) {
max_ = std::max(max_, value);
min_ = std::min(min_, value);
}

template class MemoryTrack<1>;
template class MemoryTrack<2>;
template class MemoryTrack<3>;

} // namespace orbit_gl
30 changes: 19 additions & 11 deletions src/OrbitGl/MemoryTrack.h
Expand Up @@ -8,34 +8,42 @@
#include <string>
#include <utility>

#include "AnnotationTrack.h"
#include "GraphTrack.h"
#include "Track.h"
#include "VariableTrack.h"
#include "Viewport.h"

namespace orbit_gl {

class MemoryTrack final : public VariableTrack {
constexpr std::size_t kSystemMemoryTrackSize = 3;

template <std::size_t Size>
class MemoryTrack final : public GraphTrack<Size>, public AnnotationTrack {
public:
explicit MemoryTrack(CaptureViewElement* parent, TimeGraph* time_graph,
orbit_gl::Viewport* viewport, TimeGraphLayout* layout, std::string name,
const orbit_client_model::CaptureData* capture_data)
: VariableTrack(parent, time_graph, viewport, layout, name, capture_data) {}
std::array<std::string, Size> series_names,
const orbit_client_model::CaptureData* capture_data,
uint32_t indentation_level = 0)
: Track(parent, time_graph, viewport, layout, capture_data, indentation_level),
GraphTrack<Size>(parent, time_graph, viewport, layout, name, series_names, capture_data),
AnnotationTrack(parent, time_graph, viewport, layout, capture_data, indentation_level) {}
~MemoryTrack() override = default;
[[nodiscard]] Type GetType() const override { return Type::kMemoryTrack; }
[[nodiscard]] float GetContentHeight() const override {
return size_[1] - layout_->GetTrackTabHeight() - layout_->GetTrackBottomMargin() -
GetLegendHeight();
}

void Draw(Batcher& batcher, TextRenderer& text_renderer, uint64_t current_mouse_time_ns,
PickingMode picking_mode, float z_offset = 0) override;

void SetWarningThresholdWhenEmpty(const std::string& pretty_label, double raw_value);
void SetValueUpperBoundWhenEmpty(const std::string& pretty_label, double raw_value);
void SetValueLowerBoundWhenEmpty(const std::string& pretty_label, double raw_value);
void SetWarningThresholdWhenEmpty(const std::string& pretty_label, double raw_value) override;
void SetValueUpperBoundWhenEmpty(const std::string& pretty_label, double raw_value) override;
void SetValueLowerBoundWhenEmpty(const std::string& pretty_label, double raw_value) override;

private:
void UpdateMinAndMax(double value);

std::optional<std::pair<std::string, double>> warning_threshold_ = std::nullopt;
std::optional<std::pair<std::string, double>> value_upper_bound_ = std::nullopt;
std::optional<std::pair<std::string, double>> value_lower_bound_ = std::nullopt;
};

} // namespace orbit_gl
Expand Down
31 changes: 8 additions & 23 deletions src/OrbitGl/TimeGraph.cpp
Expand Up @@ -423,9 +423,8 @@ void TimeGraph::ProcessValueTrackingTimer(const TimerInfo& timer_info) {
}

void TimeGraph::ProcessMemoryTrackingTimer(const TimerInfo& timer_info) {
const std::string kUnusedLabel = "System Memory Unused (MB)";
const std::string kBuffersOrCachedLabel = "System Memory Buffers / Cached (MB)";
const std::string kUsedLabel = "System Memory Used (MB)";
const std::array<std::string, orbit_gl::kSystemMemoryTrackSize> kSeriesNames = {
"Used", "Buffers / Cached", "Unused"};
const std::string kWarningThresholdLabel = "Production Limit";
const std::string kValueUpperBoundLabel = "System Memory Total";
const std::string kValueLowerBoundLabel = "Minimum: 0 GB";
Expand Down Expand Up @@ -454,40 +453,26 @@ void TimeGraph::ProcessMemoryTrackingTimer(const TimerInfo& timer_info) {
total_raw_value = static_cast<double>(total_kb) / kMegabytesToKilobytes;
}

MemoryTrack* track;
int64_t unused_kb = orbit_api::Decode<int64_t>(
timer_info.registers(static_cast<size_t>(OrbitApp::SystemMemoryUsageEncodingIndex::kFreeKb)));
int64_t buffers_kb = orbit_api::Decode<int64_t>(timer_info.registers(
static_cast<size_t>(OrbitApp::SystemMemoryUsageEncodingIndex::kBuffersKb)));
int64_t cached_kb = orbit_api::Decode<int64_t>(timer_info.registers(
static_cast<size_t>(OrbitApp::SystemMemoryUsageEncodingIndex::kCachedKb)));
if (buffers_kb != kMissingInfo && cached_kb != kMissingInfo) {
track = track_manager_->GetOrCreateMemoryTrack(kBuffersOrCachedLabel);
if (total_kb != kMissingInfo) {
track->SetValueUpperBoundWhenEmpty(total_pretty_label, total_raw_value);
}
track->SetValueLowerBoundWhenEmpty(kValueLowerBoundLabel, kValueLowerBoundRawValue);
track->SetLabelUnitWhenEmpty(kTrackValueLabelUnit);
track->SetValueDecimalDigitsWhenEmpty(kTrackValueDecimalDigits);
double buffers_or_cached_mb =
static_cast<double>(buffers_kb + cached_kb) / kMegabytesToKilobytes;
track->AddValue(buffers_or_cached_mb, timer_info.start());
}

if (total_kb != kMissingInfo && unused_kb != kMissingInfo && buffers_kb != kMissingInfo &&
cached_kb != kMissingInfo) {
track = track_manager_->GetOrCreateMemoryTrack(kUsedLabel);
SystemMemoryTrack* track = track_manager_->GetOrCreateSystemMemoryTrack(kSeriesNames);
track->SetValueUpperBoundWhenEmpty(total_pretty_label, total_raw_value);
track->SetValueLowerBoundWhenEmpty(kValueLowerBoundLabel, kValueLowerBoundRawValue);
if (absl::GetFlag(FLAGS_enable_warning_threshold)) {
track->SetWarningThresholdWhenEmpty(warning_threshold_pretty_label,
warning_threshold_raw_value);
}
track->SetLabelUnitWhenEmpty(kTrackValueLabelUnit);
track->SetValueDecimalDigitsWhenEmpty(kTrackValueDecimalDigits);
double unused_mb = static_cast<double>(unused_kb) / kMegabytesToKilobytes;
double buffers_or_cached_mb =
static_cast<double>(buffers_kb + cached_kb) / kMegabytesToKilobytes;
double used_mb =
static_cast<double>(total_kb - unused_kb - buffers_kb - cached_kb) / kMegabytesToKilobytes;
track->AddValue(used_mb, timer_info.start());
static_cast<double>(total_kb) / kMegabytesToKilobytes - unused_mb - buffers_or_cached_mb;
track->AddValues(timer_info.start(), {used_mb, buffers_or_cached_mb, unused_mb});
track->OnTimer(timer_info);
}
}
Expand Down
16 changes: 9 additions & 7 deletions src/OrbitGl/TrackManager.cpp
Expand Up @@ -92,8 +92,8 @@ void TrackManager::SortTracks() {
}

// Memory tracks.
for (const auto& memory_track : memory_tracks_) {
all_processes_sorted_tracks.push_back(memory_track.second.get());
if (!system_memory_track_->IsEmpty()) {
all_processes_sorted_tracks.push_back(system_memory_track_.get());
}

// Async tracks.
Expand Down Expand Up @@ -388,14 +388,16 @@ VariableTrack* TrackManager::GetOrCreateVariableTrack(const std::string& name) {
return track.get();
}

MemoryTrack* TrackManager::GetOrCreateMemoryTrack(const std::string& name) {
SystemMemoryTrack* TrackManager::GetOrCreateSystemMemoryTrack(
const std::array<std::string, orbit_gl::kSystemMemoryTrackSize>& series_names) {
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::shared_ptr<MemoryTrack> track = memory_tracks_[name];
std::shared_ptr<SystemMemoryTrack> track = system_memory_track_;
if (track == nullptr) {
track = std::make_shared<MemoryTrack>(time_graph_, time_graph_, viewport_, layout_, name,
capture_data_);
const std::string kTrackName = "System Memory Usage (MB)";
track = std::make_shared<SystemMemoryTrack>(time_graph_, time_graph_, viewport_, layout_,
kTrackName, series_names, capture_data_);
AddTrack(track);
memory_tracks_[name] = track;
system_memory_track_ = track;
}
return track.get();
}
Expand Down
8 changes: 6 additions & 2 deletions src/OrbitGl/TrackManager.h
Expand Up @@ -18,6 +18,7 @@
#include "AsyncTrack.h"
#include "FrameTrack.h"
#include "GpuTrack.h"
#include "GraphTrack.h"
#include "MemoryTrack.h"
#include "PickingManager.h"
#include "SchedulerTrack.h"
Expand All @@ -29,6 +30,8 @@
#include "Viewport.h"
#include "capture_data.pb.h"

using SystemMemoryTrack = orbit_gl::MemoryTrack<orbit_gl::kSystemMemoryTrackSize>;

class OrbitApp;
class Timegraph;

Expand Down Expand Up @@ -63,7 +66,8 @@ class TrackManager {
ThreadTrack* GetOrCreateThreadTrack(int32_t tid);
GpuTrack* GetOrCreateGpuTrack(uint64_t timeline_hash);
VariableTrack* GetOrCreateVariableTrack(const std::string& name);
orbit_gl::MemoryTrack* GetOrCreateMemoryTrack(const std::string& name);
SystemMemoryTrack* GetOrCreateSystemMemoryTrack(
const std::array<std::string, orbit_gl::kSystemMemoryTrackSize>& series_names);
AsyncTrack* GetOrCreateAsyncTrack(const std::string& name);
FrameTrack* GetOrCreateFrameTrack(const orbit_grpc_protos::InstrumentedFunction& function);

Expand All @@ -90,7 +94,6 @@ class TrackManager {
absl::flat_hash_map<int32_t, std::shared_ptr<ThreadTrack>> thread_tracks_;
std::map<std::string, std::shared_ptr<AsyncTrack>> async_tracks_;
std::map<std::string, std::shared_ptr<VariableTrack>> variable_tracks_;
std::map<std::string, std::shared_ptr<orbit_gl::MemoryTrack>> memory_tracks_;
// Mapping from timeline to GPU tracks. Timeline name is used for stable ordering. In particular
// we want the marker tracks next to their queue track. E.g. "gfx" and "gfx_markers" should appear
// next to each other.
Expand All @@ -100,6 +103,7 @@ class TrackManager {
std::map<uint64_t, std::shared_ptr<FrameTrack>> frame_tracks_;
std::shared_ptr<SchedulerTrack> scheduler_track_;
ThreadTrack* tracepoints_system_wide_track_;
std::shared_ptr<SystemMemoryTrack> system_memory_track_;

TimeGraph* time_graph_;
orbit_gl::Viewport* viewport_;
Expand Down

0 comments on commit a15ed0d

Please sign in to comment.