xo-imgui: imgui_ex4: prep gc history bars for rich tooltips
This commit is contained in:
parent
b4a8ecd7d6
commit
51a1ce7d0f
5 changed files with 152 additions and 126 deletions
|
|
@ -244,82 +244,92 @@ DrawState::draw_tenured(const GcStateDescription & gcstate,
|
|||
*p_layout = layout;
|
||||
}
|
||||
|
||||
auto
|
||||
DrawState::write_gc_history_tooltip(gc_history_headline headline,
|
||||
const GcStatisticsHistoryItem & stats)
|
||||
-> TooltipText
|
||||
#ifdef nope
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ypsz_lo, y_zero)),
|
||||
persist_color,
|
||||
draw_list);
|
||||
#endif
|
||||
|
||||
void
|
||||
DrawState::write_gc_history_bar(const char * idname,
|
||||
gc_history_headline headline,
|
||||
const GcStatisticsHistoryItem & stats,
|
||||
const ImRect & bar_rect,
|
||||
ImU32 fill_color,
|
||||
ImDrawList * draw_list)
|
||||
{
|
||||
xo::flatstring<512> retval;
|
||||
draw_list->AddRectFilled(bar_rect.top_left(), bar_rect.bottom_right(), fill_color);
|
||||
|
||||
xo::flatstring<256> headline_str;
|
||||
switch (headline) {
|
||||
case gc_history_headline::survive:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"survive: %lu: bytes surviving 1st GC after allocation",
|
||||
stats.survive_z_);
|
||||
break;
|
||||
case gc_history_headline::promote:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"promote: %lu: bytes surviving 2nd GC; if nursery promote to tenured",
|
||||
stats.promote_z_);
|
||||
break;
|
||||
case gc_history_headline::persist:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"persist: %lu: bytes surviving 3+ GCs. Only non-zero for full collections",
|
||||
stats.persist_z_);
|
||||
break;
|
||||
case gc_history_headline::garbage0:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"garbage\u2080: %lu: bytes collected on 1st GC after allocation",
|
||||
stats.garbage0_z_);
|
||||
break;
|
||||
case gc_history_headline::garbage1:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"garbage\u2081: %lu: bytes collected on 2nd GC after allocation",
|
||||
stats.garbage1_z_);
|
||||
break;
|
||||
case gc_history_headline::garbageN:
|
||||
snprintf(headline_str.data(), headline_str.capacity(),
|
||||
"garbage\u2099: %lu: bytes collected on 3rd or later GC after allocation",
|
||||
stats.garbageN_z_);
|
||||
break;
|
||||
case gc_history_headline::N:
|
||||
assert(false);
|
||||
break;
|
||||
if (bar_rect.is_nonempty()) {
|
||||
ImGui::SetCursorScreenPos(bar_rect.top_left());
|
||||
ImGui::InvisibleButton(idname, ImVec2(bar_rect.width(), bar_rect.height()));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
/* choose text here */
|
||||
switch(headline) {
|
||||
case gc_history_headline::survive:
|
||||
ImGui::Text("survive: %lu: bytes surviving 1st GC after allocation",
|
||||
stats.survive_z_);
|
||||
break;
|
||||
case gc_history_headline::promote:
|
||||
ImGui::Text("promote: %lu: bytes surviving 2nd GC; if nursery promote to tenured",
|
||||
stats.promote_z_);
|
||||
break;
|
||||
case gc_history_headline::persist:
|
||||
ImGui::Text("persist: %lu: bytes surviving 3+ GCs. Only non-zero for full collections",
|
||||
stats.persist_z_);
|
||||
break;
|
||||
case gc_history_headline::garbage0:
|
||||
ImGui::Text("garbage\u2080: %lu: bytes collected on 1st GC after allocation",
|
||||
stats.garbage0_z_);
|
||||
break;
|
||||
case gc_history_headline::garbage1:
|
||||
ImGui::Text("garbage\u2081: %lu: bytes collected on 2nd GC after allocation",
|
||||
stats.garbage1_z_);
|
||||
break;
|
||||
case gc_history_headline::garbageN:
|
||||
ImGui::Text("garbage\u2099: %lu: bytes collected on 3rd or later GC after allocation",
|
||||
stats.garbageN_z_);
|
||||
break;
|
||||
case gc_history_headline::N:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::Text("\n"
|
||||
" gcseq: %lu\n"
|
||||
" type: %s\n"
|
||||
" alloc: %lu\n"
|
||||
" survive: %lu\n"
|
||||
" promote: %lu\n"
|
||||
" persist: %lu\n"
|
||||
" garbage\u2080: %lu\n" /*garbage0*/
|
||||
" garbage\u2081: %lu\n" /*garbage1*/
|
||||
" garbage\u2099: %lu\n" /*garbageN*/
|
||||
" effort: %lu dt: %.1lfus\n"
|
||||
" copy efficiency: %.1lf%% collection rate: %.0lf bytes/sec",
|
||||
stats.gc_seq_,
|
||||
(stats.upto_ == generation::nursery) ? "incremental" : "FULL",
|
||||
stats.new_alloc_z_,
|
||||
stats.survive_z_,
|
||||
stats.promote_z_,
|
||||
stats.persist_z_,
|
||||
stats.garbage0_z_,
|
||||
stats.garbage1_z_,
|
||||
stats.garbageN_z_,
|
||||
stats.effort_z_,
|
||||
1e-3 * stats.dt_.scale(),
|
||||
100.0 * stats.efficiency(),
|
||||
stats.collection_rate()
|
||||
);
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(retval.data(), retval.capacity(),
|
||||
"%.*s\n"
|
||||
"\n"
|
||||
" gcseq: %lu\n"
|
||||
" type: %s\n"
|
||||
" alloc: %lu\n"
|
||||
" survive: %lu\n"
|
||||
" promote: %lu\n"
|
||||
" persist: %lu\n"
|
||||
" garbage\u2080: %lu\n" /*garbage0*/
|
||||
" garbage\u2081: %lu\n" /*garbage1*/
|
||||
" garbage\u2099: %lu\n" /*garbageN*/
|
||||
" effort: %lu dt: %.1lfus\n"
|
||||
" copy efficiency: %.1lf%% collection rate: %.0lf bytes/sec",
|
||||
static_cast<int>(headline_str.capacity()), headline_str.c_str(),
|
||||
stats.gc_seq_,
|
||||
(stats.upto_ == generation::nursery) ? "incremental" : "FULL",
|
||||
stats.new_alloc_z_,
|
||||
stats.survive_z_,
|
||||
stats.promote_z_,
|
||||
stats.persist_z_,
|
||||
stats.garbage0_z_,
|
||||
stats.garbage1_z_,
|
||||
stats.garbageN_z_,
|
||||
stats.effort_z_,
|
||||
1e-3 * stats.dt_.scale(),
|
||||
100.0 * stats.efficiency(),
|
||||
stats.collection_rate()
|
||||
);
|
||||
|
||||
return retval.ensure_final_null();
|
||||
} /*write_gc_history_tooltip*/
|
||||
} /*write_gc_history_bar*/
|
||||
|
||||
/** stacked bar chart
|
||||
*
|
||||
|
|
@ -384,6 +394,8 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
std::size_t i = 0;
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history)
|
||||
{
|
||||
ImGui::PushID(i);
|
||||
|
||||
if ((gen == stats.upto_) || (gen == generation::tenured))
|
||||
{
|
||||
/*
|
||||
|
|
@ -424,39 +436,36 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
float ypsz_lo = (y_zero
|
||||
- (display_h * stats.persist_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<512> tt = write_gc_history_tooltip(gc_history_headline::persist, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ypsz_lo, y_zero)),
|
||||
persist_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##persist",
|
||||
gc_history_headline::persist,
|
||||
stats,
|
||||
ImRect::from_xy_span(x_span, ImVec2(ypsz_lo, y_zero)),
|
||||
persist_color,
|
||||
draw_list);
|
||||
}
|
||||
/* y-coordinates of promote bar (survived 2nd GC) */
|
||||
float yp_hi = ypsz_lo;
|
||||
float yp_lo = (yp_hi
|
||||
- (display_h * stats.promote_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<512> tt = write_gc_history_tooltip(gc_history_headline::promote, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(yp_lo, yp_hi)),
|
||||
promote_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##promote",
|
||||
gc_history_headline::promote,
|
||||
stats,
|
||||
ImRect::from_xy_span(x_span, ImVec2(yp_lo, yp_hi)),
|
||||
promote_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
/* y-coordinates of survivor bar (survived 1st GC) */
|
||||
float ys_hi = yp_lo;
|
||||
float ys_lo = (ys_hi - (display_h * stats.survive_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<512> tt = write_gc_history_tooltip(gc_history_headline::survive, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ys_lo, ys_hi)),
|
||||
survive_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##survivor",
|
||||
gc_history_headline::survive,
|
||||
stats,
|
||||
ImRect::from_xy_span(x_span, ImVec2(ys_lo, ys_hi)),
|
||||
survive_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
|
@ -466,13 +475,12 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
float ygN_hi = (y_zero
|
||||
+ (display_h * stats.garbageN_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<512> tt = write_gc_history_tooltip(gc_history_headline::garbageN, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ygN_lo, ygN_hi)),
|
||||
garbageN_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##garbageN",
|
||||
gc_history_headline::garbageN,
|
||||
stats,
|
||||
ImRect::from_xy_span(x_span, ImVec2(ygN_lo, ygN_hi)),
|
||||
garbageN_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
/* y-coordinates of garbage1 bar (killed on 2nd GC) */
|
||||
|
|
@ -480,13 +488,12 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
float yg1_hi = (yg1_lo
|
||||
+ (display_h * stats.garbage1_z_ / y_scale));
|
||||
{
|
||||
TooltipText tt = write_gc_history_tooltip(gc_history_headline::garbage1, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect(ImVec2(x_lo, yg1_lo), ImVec2(x_hi, yg1_hi)),
|
||||
garbage1_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##garbage1",
|
||||
gc_history_headline::garbage1,
|
||||
stats,
|
||||
ImRect(ImVec2(x_lo, yg1_lo), ImVec2(x_hi, yg1_hi)),
|
||||
garbage1_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
/* y-coordinates of garbage0 bar (killed on 1st GC) */
|
||||
|
|
@ -494,13 +501,12 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
float yg0_hi = (yg0_lo
|
||||
+ (display_h * stats.garbage0_z_ / y_scale));
|
||||
{
|
||||
TooltipText tt = write_gc_history_tooltip(gc_history_headline::garbage0, stats);
|
||||
|
||||
ImRect::draw_filled_rect
|
||||
(tt.c_str(),
|
||||
ImRect(ImVec2(x_lo, yg0_lo), ImVec2(x_hi, yg0_hi)),
|
||||
garbage0_color,
|
||||
draw_list);
|
||||
write_gc_history_bar("##garbage0",
|
||||
gc_history_headline::garbage0,
|
||||
stats,
|
||||
ImRect(ImVec2(x_lo, yg0_lo), ImVec2(x_hi, yg0_hi)),
|
||||
garbage0_color,
|
||||
draw_list);
|
||||
}
|
||||
} else {
|
||||
/* draw nothing */
|
||||
|
|
@ -508,6 +514,8 @@ DrawState::draw_gc_history(const GcStateDescription & gcstate,
|
|||
}
|
||||
|
||||
++i;
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
log && log(xtag("i", i));
|
||||
|
|
|
|||
|
|
@ -47,8 +47,22 @@ struct DrawState {
|
|||
const ImRect & rect,
|
||||
ImDrawList * draw_list,
|
||||
GenerationLayout * p_layout);
|
||||
static TooltipText write_gc_history_tooltip(gc_history_headline headline,
|
||||
const GcStatisticsHistoryItem & stats);
|
||||
/**
|
||||
* display one bar in bar strip chart displaying gc statistics
|
||||
*
|
||||
* @p idname : name for invisible button widget (expected to be unique)
|
||||
* @p headline : purpose of rectangle
|
||||
* @p stats : gc statistics for this bar.
|
||||
* @p bar_rect : rectangle representing quantity in bytes
|
||||
* @p fill_color : rectangle fill color
|
||||
* @p draw_list : draw list for current frame
|
||||
**/
|
||||
static void write_gc_history_bar(const char * idname,
|
||||
gc_history_headline headline,
|
||||
const GcStatisticsHistoryItem & stats,
|
||||
const ImRect & bar_rect,
|
||||
ImU32 fill_color,
|
||||
ImDrawList * draw_list);
|
||||
static void draw_gc_history(const GcStateDescription & gcstate,
|
||||
generation gen,
|
||||
const GcStatisticsHistory & gc_history,
|
||||
|
|
|
|||
|
|
@ -75,12 +75,11 @@ namespace {
|
|||
VulkanApp::ImguiDrawFn
|
||||
make_imgui_draw_frame(AppState * p_app_state,
|
||||
DrawState * p_draw_state,
|
||||
float * p_f, int * p_counter)
|
||||
int * p_counter)
|
||||
{
|
||||
*p_f = 0.0f;
|
||||
*p_counter = 0;
|
||||
|
||||
return [p_app_state, p_draw_state, p_f, p_counter](VulkanApp * vulkan_app, ImGuiContext * imgui_cx)
|
||||
return [p_app_state, p_draw_state, p_counter](VulkanApp * vulkan_app, ImGuiContext * imgui_cx)
|
||||
{
|
||||
scope log(XO_DEBUG(false));
|
||||
|
||||
|
|
@ -123,7 +122,7 @@ namespace {
|
|||
|
||||
// 1. create a simple ImGui window
|
||||
ImGui::Begin("Hello, Vulkan + SDL2!");
|
||||
ImGui::Text("This is a minimal ImGui + Vulkan + SDL2 example!");
|
||||
ImGui::Text("Incremental GC demo, using ImGui + Vulkan + SDL2");
|
||||
ImGui::Text("appl average %.3f ms/frame (%.1f fps)",
|
||||
1000.0f / io.Framerate, io.Framerate);
|
||||
|
||||
|
|
@ -133,7 +132,9 @@ namespace {
|
|||
ImGui::SliderInt("copy animation budget", &p_draw_state->animate_copy_budget_ms_, 10, 10000);
|
||||
ImGui::NewLine();
|
||||
|
||||
/* N\u2080 = N0, N\u2081 = N1 */
|
||||
/* N\u2080 -> N0, but with the 0 subscripted,
|
||||
* N\u2081 -> N1, but with the 1 subscripted
|
||||
*/
|
||||
ImGui::Text("alloc [%lu] avail [%lu] ",
|
||||
p_draw_state->gcstate_.gc_allocated_,
|
||||
p_draw_state->gcstate_.gc_available_);
|
||||
|
|
@ -292,10 +293,9 @@ int main() {
|
|||
DrawState draw_state;
|
||||
draw_state.gcstate_ = app_state.snapshot_gc_state();
|
||||
|
||||
float f = 0.0;
|
||||
int counter = 0;
|
||||
VulkanApp::ImguiDrawFn draw_fn
|
||||
= make_imgui_draw_frame(&app_state, &draw_state, &f, &counter);
|
||||
= make_imgui_draw_frame(&app_state, &draw_state, &counter);
|
||||
VulkanApp vk_app(draw_fn);
|
||||
|
||||
vk_app.setup(app_imgui_load_fonts);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ struct ImRect {
|
|||
ImVec2 bottom_left() const { return ImVec2(x_lo(), y_hi()); }
|
||||
ImVec2 top_right() const { return ImVec2(x_hi(), y_lo()); }
|
||||
|
||||
bool is_nonempty() const { return (width() > 0.0) && (height() > 0.0); }
|
||||
|
||||
ImRect with_x_span(float x0, float x1) const {
|
||||
return ImRect(ImVec2(x0, top_left_.y), ImVec2(x1, bottom_right_.y));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ ImRect::draw_filled_rect_with_label(const char * text,
|
|||
ImGui::SetCursorScreenPos(rect.top_left());
|
||||
ImGui::InvisibleButton("ttbutton", ImVec2(rect.width(), rect.height()));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("%s", tooltip);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", tooltip);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue