xo-imgui: ex2: + average efficiency + plot
This commit is contained in:
parent
d97078dc41
commit
4a7463edcc
3 changed files with 218 additions and 51 deletions
|
|
@ -163,17 +163,23 @@ namespace xo {
|
|||
std::size_t garbage0_z,
|
||||
std::size_t garbage1_z,
|
||||
std::size_t garbageN_z,
|
||||
nanos dt) : gc_seq_{gc_seq},
|
||||
upto_{upto},
|
||||
new_alloc_z_{new_alloc_z},
|
||||
survive_z_{survive_z},
|
||||
promote_z_{promote_z},
|
||||
persist_z_{persist_z},
|
||||
effort_z_{effort_z},
|
||||
garbage0_z_{garbage0_z},
|
||||
garbage1_z_{garbage1_z},
|
||||
garbageN_z_{garbageN_z},
|
||||
dt_{dt} {}
|
||||
nanos dt,
|
||||
std::size_t sum_effort_z,
|
||||
std::size_t sum_garbage_z)
|
||||
: gc_seq_{gc_seq},
|
||||
upto_{upto},
|
||||
new_alloc_z_{new_alloc_z},
|
||||
survive_z_{survive_z},
|
||||
promote_z_{promote_z},
|
||||
persist_z_{persist_z},
|
||||
effort_z_{effort_z},
|
||||
garbage0_z_{garbage0_z},
|
||||
garbage1_z_{garbage1_z},
|
||||
garbageN_z_{garbageN_z},
|
||||
dt_{dt},
|
||||
sum_effort_z_{sum_effort_z},
|
||||
sum_garbage_z_{sum_garbage_z}
|
||||
{}
|
||||
constexpr GcStatisticsHistoryItem(const GcStatisticsHistoryItem &) = default;
|
||||
|
||||
std::size_t garbage_z() const { return garbage0_z_ + garbage1_z_ + garbageN_z_; }
|
||||
|
|
@ -184,6 +190,11 @@ namespace xo {
|
|||
return gz / static_cast<float>(effort_z_ + gz);
|
||||
}
|
||||
|
||||
/** lifetime byte-weighted average collection efficiency. Always in [0.0, 1.0] **/
|
||||
float average_efficiency() const {
|
||||
return sum_garbage_z_ / static_cast<float>(sum_effort_z_ + sum_garbage_z_);
|
||||
}
|
||||
|
||||
/** collection rate, in bytes/sec **/
|
||||
float collection_rate() const;
|
||||
|
||||
|
|
@ -199,6 +210,10 @@ namespace xo {
|
|||
garbage1_z_ = x.garbage1_z_;
|
||||
garbageN_z_ = x.garbageN_z_;
|
||||
this->dt_.scale_ = x.dt_.scale_;
|
||||
|
||||
sum_effort_z_ = x.sum_effort_z_;
|
||||
sum_garbage_z_ = x.sum_garbage_z_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +244,13 @@ namespace xo {
|
|||
std::size_t garbageN_z_ = 0;
|
||||
/** elapsed time for this GC (see @ref GC::execute_gc) **/
|
||||
nanos dt_;
|
||||
|
||||
// ----- cumulative statistics -----
|
||||
|
||||
/** sum (in bytes) copied by collections since inception **/
|
||||
std::size_t sum_effort_z_ = 0;
|
||||
/** sum (in bytes) of garbage collected since inception **/
|
||||
std::size_t sum_garbage_z_ = 0;
|
||||
};
|
||||
|
||||
inline std::ostream & operator<< (std::ostream & os, const GcStatisticsHistoryItem & x) {
|
||||
|
|
|
|||
|
|
@ -1119,6 +1119,15 @@ namespace xo {
|
|||
// still want to update tenured stats for current alloc size
|
||||
this->gc_statistics_.update_snapshot(generation::tenured, T_after_gc);
|
||||
}
|
||||
|
||||
std::size_t sum_effort_z = effort_z;
|
||||
std::size_t sum_garbage_z = garbage0_z + garbage1_z + garbageN_z;
|
||||
|
||||
if (gc_history_.size() > 0) {
|
||||
sum_effort_z += gc_history_.back().sum_effort_z_;
|
||||
sum_garbage_z += gc_history_.back().sum_garbage_z_;
|
||||
}
|
||||
|
||||
GcStatisticsHistoryItem item(gc_statistics_.n_gc(),
|
||||
upto,
|
||||
new_alloc_z,
|
||||
|
|
@ -1129,7 +1138,9 @@ namespace xo {
|
|||
garbage0_z,
|
||||
garbage1_z,
|
||||
garbageN_z,
|
||||
dt);
|
||||
dt,
|
||||
sum_effort_z,
|
||||
sum_garbage_z);
|
||||
|
||||
log && log(xtag("gcseq_after_gc", gc_statistics_.n_gc()),
|
||||
xtag("item", item));
|
||||
|
|
|
|||
|
|
@ -73,6 +73,16 @@ struct ImRect {
|
|||
return ImRect(ImVec2(top_left_.x, y0), ImVec2(bottom_right_.x, y1));
|
||||
}
|
||||
|
||||
/** Require: 0.0 <= p <= 1.0 **/
|
||||
ImRect top_fraction(float p) const {
|
||||
return ImRect(top_left_, ImVec2(this->x_hi(), ((1.0 - p) * this->y_lo()) + (p * this->y_hi())));
|
||||
}
|
||||
|
||||
/** Require: 0.0 <= p <= 1.0 **/
|
||||
ImRect bottom_fraction(float p) const {
|
||||
return ImRect(ImVec2(this->x_lo(), (p * this->y_lo()) + ((1.0 - p) * this->y_hi())), bottom_right_);
|
||||
}
|
||||
|
||||
ImVec2 top_left_{0, 0};
|
||||
ImVec2 bottom_right_{0, 0};
|
||||
};
|
||||
|
|
@ -724,7 +734,9 @@ write_gc_history_tooltip(gc_history_headline headline,
|
|||
return retval.ensure_final_null();
|
||||
}
|
||||
|
||||
/** @param gen if @ref generation::nursery, only display nursery collections.
|
||||
/** stacked bar chart
|
||||
*
|
||||
* @param gen if @ref generation::nursery, only display nursery collections.
|
||||
* otherwise display both
|
||||
**/
|
||||
void
|
||||
|
|
@ -778,7 +790,8 @@ draw_gc_history(const GcStateDescription & gcstate,
|
|||
float y_scale = yplus_scale + yminus_scale;
|
||||
|
||||
/* width of 1 bar in screen coords */
|
||||
float bar_w = display_w / gc_history.capacity();
|
||||
constexpr float c_min_bar_w = 5.0;
|
||||
float bar_w = std::max(c_min_bar_w, display_w / gc_history.capacity());
|
||||
|
||||
/* 2nd loop: draw bars */
|
||||
std::size_t i = 0;
|
||||
|
|
@ -907,6 +920,100 @@ draw_gc_history(const GcStateDescription & gcstate,
|
|||
log && log(xtag("i", i));
|
||||
}
|
||||
|
||||
void
|
||||
draw_gc_efficiency(const GcStateDescription & gcstate,
|
||||
//generation gen,
|
||||
const GcStatisticsHistory & gc_history,
|
||||
const ImRect & bounding_rect,
|
||||
bool debug_flag,
|
||||
ImDrawList * draw_list)
|
||||
{
|
||||
scope log(XO_DEBUG(debug_flag));
|
||||
|
||||
float lm = 10;
|
||||
float tm = 25;
|
||||
|
||||
/* we're going to make a level chart */
|
||||
|
||||
/* x_scale,y_scale in GC units (i.e. bytes) */
|
||||
size_t x_scale = gc_history.capacity();
|
||||
size_t yplus_scale = 1;
|
||||
size_t yminus_scale = 0;
|
||||
|
||||
float display_w = bounding_rect.width() - lm;
|
||||
float display_h = bounding_rect.height() - tm;
|
||||
|
||||
#ifdef NOPE // don't need this. y-scale is [0.0, 1.0]
|
||||
/* 1st loop: figure out max y scale */
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history) {
|
||||
if ((gen == stats.upto_) || (gen == generation::tenured))
|
||||
{
|
||||
//size_t na = stats.new_alloc_z_ - stats.survive_z_; /*new allocs, but dont' double-count survive_z*/
|
||||
size_t sz = stats.survive_z_; /*survive 1st gc */
|
||||
size_t pz = stats.promote_z_; /*survive 2nd gc */
|
||||
size_t psz = stats.persist_z_; /*survive 3+ gc */
|
||||
size_t g0z = stats.garbage0_z_;
|
||||
size_t g1z = stats.garbage1_z_;
|
||||
size_t gNz = stats.garbageN_z_;
|
||||
|
||||
if (yplus_scale < sz + pz + psz)
|
||||
yplus_scale = sz + pz + psz;
|
||||
|
||||
if (yminus_scale < g0z + g1z + gNz)
|
||||
yminus_scale = g0z + g1z + gNz;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* y-coord of x-axis */
|
||||
float y_zero = bounding_rect.y_lo() + tm + display_h;
|
||||
//float y_zero = bounding_rect.y_lo() + tm + (display_h * yplus_scale) / (yplus_scale + yminus_scale);
|
||||
|
||||
float y_scale = 1.0;
|
||||
|
||||
/* width of 1 bar in screen coords */
|
||||
constexpr float c_min_bar_w = 5.0;
|
||||
float bar_w = std::max(c_min_bar_w, display_w / gc_history.capacity());
|
||||
|
||||
/* TODO: use temporary arena */
|
||||
std::vector<ImVec2> line_points;
|
||||
line_points.reserve(gc_history.size());
|
||||
|
||||
ImU32 average_color = IM_COL32(255, 255, 64, 255); /*solid yellow*/
|
||||
ImU32 sample_color = IM_COL32(255, 255, 255, 255); /*white*/
|
||||
|
||||
/* 2nd loop: draw levels */
|
||||
std::size_t i = 0;
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history)
|
||||
{
|
||||
//std::vector<ImVec2> line_points = { /* your points */ };
|
||||
//draw_list->AddPolyline(line_points.data(), line_points.size(),
|
||||
// IM_COL32(255, 255, 0, 255), false, 2.0f);
|
||||
|
||||
float y = y_zero - display_h * stats.efficiency();
|
||||
float y_mean = y_zero - display_h * stats.average_efficiency();
|
||||
|
||||
/* x-coordinates of point */
|
||||
float x = bounding_rect.x_lo() + lm + i * bar_w + 0.5 * bar_w;
|
||||
|
||||
line_points.push_back(ImVec2(x, y_mean));
|
||||
|
||||
draw_list->AddCircleFilled(ImVec2(x, y), 2.0f, sample_color);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
draw_list->AddPolyline(line_points.data(),
|
||||
line_points.size(),
|
||||
average_color,
|
||||
false,
|
||||
1.0f /*line width?*/);
|
||||
|
||||
log && log(xtag("i", i));
|
||||
} /*draw_gc_efficiency*/
|
||||
|
||||
void
|
||||
draw_gc_alloc_state(const GcStateDescription & gcstate,
|
||||
const ImRect & canvas_rect,
|
||||
|
|
@ -1024,53 +1131,80 @@ draw_gc_state(const AppState & app_state,
|
|||
IM_COL32(255, 255, 255, 255));
|
||||
|
||||
/* TODO: does this reset coord space? */
|
||||
ImGui::BeginChild("top pane", ImVec2(0, 105), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY);
|
||||
ImRect alloc_rect;
|
||||
{
|
||||
ImGui::BeginChild("top pane", ImVec2(0, 105), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY);
|
||||
|
||||
ImRect alloc_rect(canvas_rect.top_left() + ImGui::GetWindowContentRegionMin(),
|
||||
canvas_rect.top_left() + ImGui::GetWindowContentRegionMax());
|
||||
alloc_rect = ImRect(canvas_rect.top_left() + ImGui::GetWindowContentRegionMin(),
|
||||
canvas_rect.top_left() + ImGui::GetWindowContentRegionMax());
|
||||
|
||||
draw_list->PushClipRect(alloc_rect.top_left(), alloc_rect.bottom_right());
|
||||
draw_list->PushClipRect(alloc_rect.top_left(), alloc_rect.bottom_right());
|
||||
|
||||
draw_gc_alloc_state(gcstate,
|
||||
alloc_rect,
|
||||
draw_list,
|
||||
p_nursery_alloc_rect,
|
||||
p_tenured_alloc_rect);
|
||||
draw_gc_alloc_state(gcstate,
|
||||
alloc_rect,
|
||||
draw_list,
|
||||
p_nursery_alloc_rect,
|
||||
p_tenured_alloc_rect);
|
||||
|
||||
draw_list->PopClipRect();
|
||||
draw_list->PopClipRect();
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImRect history_rect;
|
||||
{
|
||||
ImGui::BeginChild("left pane", ImVec2(800, 0), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX);
|
||||
|
||||
history_rect = ImRect(alloc_rect.bottom_left() + ImGui::GetWindowContentRegionMin(),
|
||||
alloc_rect.bottom_left() + ImGui::GetWindowContentRegionMax());
|
||||
|
||||
draw_list->PushClipRect(history_rect.top_left(), history_rect.bottom_right());
|
||||
|
||||
float lm = 50;
|
||||
float rm = 70;
|
||||
float tm = 10;
|
||||
std::size_t x0 = history_rect.x_lo() + lm;
|
||||
std::size_t x1 = history_rect.x_hi() - rm;
|
||||
std::size_t h_y0 = history_rect.y_lo() + tm;
|
||||
|
||||
/* just incremental (nursery) collections */
|
||||
ImRect incremental_rect = history_rect.top_fraction(0.33);
|
||||
|
||||
draw_gc_history(gcstate,
|
||||
generation::nursery,
|
||||
app_state.gc_->gc_history(),
|
||||
incremental_rect,
|
||||
false /*debug_flag*/,
|
||||
draw_list);
|
||||
|
||||
/* just full (nursery+tenured) collections */
|
||||
ImRect full_rect = history_rect.bottom_fraction(0.67).top_fraction(0.5);
|
||||
|
||||
/* both nursery + full collections */
|
||||
draw_gc_history(gcstate,
|
||||
generation::tenured,
|
||||
app_state.gc_->gc_history(),
|
||||
full_rect,
|
||||
false /*debug_flag*/,
|
||||
draw_list);
|
||||
|
||||
ImRect efficiency_rect = history_rect.bottom_fraction(0.67).bottom_fraction(0.5);
|
||||
|
||||
draw_gc_efficiency(gcstate,
|
||||
app_state.gc_->gc_history(),
|
||||
efficiency_rect,
|
||||
false /*debug_flag*/,
|
||||
draw_list);
|
||||
|
||||
draw_list->PopClipRect();
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::Text("placeholder text");
|
||||
|
||||
/* BeginChild() again ? */
|
||||
|
||||
ImRect history_rect(alloc_rect.bottom_left() + ImGui::GetWindowContentRegionMin(),
|
||||
alloc_rect.bottom_left() + ImGui::GetWindowContentRegionMax());
|
||||
|
||||
float lm = 50;
|
||||
float rm = 70;
|
||||
float tm = 10;
|
||||
std::size_t x0 = history_rect.x_lo() + lm;
|
||||
std::size_t x1 = history_rect.x_hi() - rm;
|
||||
std::size_t h_y0 = history_rect.y_lo() + tm;
|
||||
|
||||
/* just incremental (nursery) collections */
|
||||
draw_gc_history(gcstate,
|
||||
generation::nursery,
|
||||
app_state.gc_->gc_history(),
|
||||
ImRect(ImVec2(x0, h_y0),
|
||||
ImVec2(x1, h_y0 + 250)),
|
||||
false /*debug_flag*/,
|
||||
draw_list);
|
||||
|
||||
/* both nursery + full collections */
|
||||
draw_gc_history(gcstate,
|
||||
generation::tenured,
|
||||
app_state.gc_->gc_history(),
|
||||
ImRect(ImVec2(x0, h_y0 + 250),
|
||||
ImVec2(x1, h_y0 + 500)),
|
||||
false /*debug_flag*/,
|
||||
draw_list);
|
||||
|
||||
#ifdef NOPE
|
||||
draw_list->AddCircleFilled(ImVec2(canvas_p0.x + 50, canvas_p0.y + 50),
|
||||
30.0f, IM_COL32(255, 0, 0, 255));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue