xo-alloc: + timing stats + timeseries tooltips
This commit is contained in:
parent
5eb58b7d37
commit
7c846f9ad0
7 changed files with 360 additions and 101 deletions
|
|
@ -132,6 +132,7 @@ namespace xo {
|
|||
public:
|
||||
using CallbackId = xo::fn::CallbackId;
|
||||
using GcCopyCallbackSet = xo::fn::UpCallbackSet<GcCopyCallback>;
|
||||
using nanos = decltype(xo::qty::qty::nanosecond);
|
||||
|
||||
public:
|
||||
/** create new GC instance with configuration @p config **/
|
||||
|
|
@ -224,6 +225,8 @@ namespace xo {
|
|||
* as number of calls to @ref disable_gc.
|
||||
**/
|
||||
void enable_gc();
|
||||
/** same as @c this->enable_gc() followed by @c this->disable_gc() **/
|
||||
void enable_gc_once();
|
||||
|
||||
// inherited from IAlloc..
|
||||
|
||||
|
|
@ -279,7 +282,7 @@ namespace xo {
|
|||
/** begin GC now **/
|
||||
void execute_gc(generation g);
|
||||
/** cleanup phase. aux function for @ref execute_gc **/
|
||||
void cleanup_phase(generation g);
|
||||
void cleanup_phase(generation g, nanos dt);
|
||||
/** swap roles of From/To spaces for nursery generation **/
|
||||
void swap_nursery();
|
||||
/** swap roles of From/To spaces for tenured generation **/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include "generation.hpp"
|
||||
#include "CircularBuffer.hpp"
|
||||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "xo/unit/quantity.hpp"
|
||||
#include "xo/unit/quantity_iostream.hpp"
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
#include <ostream>
|
||||
#include <array>
|
||||
|
|
@ -60,6 +62,13 @@ namespace xo {
|
|||
public:
|
||||
GcStatistics() = default;
|
||||
|
||||
/** update statistics at beginning of a GC cycle
|
||||
* @param upto. nursery -> incremental collection; tenured -> full collection
|
||||
* @param alloc_z. new allocations (since preceding GC)
|
||||
**/
|
||||
void begin_gc(generation upto,
|
||||
std::size_t alloc_z);
|
||||
|
||||
/** update statistics after a GC cycle
|
||||
* @param upto. nursery -> incremental collection; tenured -> full collection
|
||||
* @param alloc_z. new allocations (since preceding GC)
|
||||
|
|
@ -74,6 +83,9 @@ namespace xo {
|
|||
**/
|
||||
void update_snapshot(generation upto, std::size_t after_z);
|
||||
|
||||
/** number of collection cycles, whether full or incremental **/
|
||||
std::size_t n_gc() const { return gen_v_[gen2int(generation::nursery)].n_gc_; }
|
||||
|
||||
/** @param os. write stats on this output stream **/
|
||||
void display(std::ostream & os) const;
|
||||
|
||||
|
|
@ -136,31 +148,54 @@ namespace xo {
|
|||
* @brief info we want to record over time (won't have cumulative things in it)
|
||||
**/
|
||||
class GcStatisticsHistoryItem {
|
||||
public:
|
||||
using nanos = xo::qty::type::nanoseconds<std::int64_t>;
|
||||
|
||||
public:
|
||||
GcStatisticsHistoryItem() = default;
|
||||
GcStatisticsHistoryItem(generation upto,
|
||||
std::size_t new_alloc_z,
|
||||
std::size_t survive_z,
|
||||
std::size_t promote_z,
|
||||
std::size_t persist_z,
|
||||
std::size_t effort_z,
|
||||
std::size_t garbage0_z,
|
||||
std::size_t garbage1_z,
|
||||
std::size_t garbageN_z)
|
||||
: 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}
|
||||
{}
|
||||
constexpr GcStatisticsHistoryItem(std::size_t gc_seq,
|
||||
generation upto,
|
||||
std::size_t new_alloc_z,
|
||||
std::size_t survive_z,
|
||||
std::size_t promote_z,
|
||||
std::size_t persist_z,
|
||||
std::size_t effort_z,
|
||||
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} {}
|
||||
constexpr GcStatisticsHistoryItem(const GcStatisticsHistoryItem &) = default;
|
||||
|
||||
GcStatisticsHistoryItem & operator=(const GcStatisticsHistoryItem & x) {
|
||||
gc_seq_ = x.gc_seq_;
|
||||
upto_ = x.upto_;
|
||||
new_alloc_z_ = x.new_alloc_z_;
|
||||
survive_z_ = x.survive_z_;
|
||||
promote_z_ = x.promote_z_;
|
||||
persist_z_ = x.persist_z_;
|
||||
effort_z_ = x.effort_z_;
|
||||
garbage0_z_ = x.garbage0_z_;
|
||||
garbage1_z_ = x.garbage1_z_;
|
||||
garbageN_z_ = x.garbageN_z_;
|
||||
this->dt_.scale_ = x.dt_.scale_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @param os. write stats on this output stream **/
|
||||
void display(std::ostream & os) const;
|
||||
|
||||
/** sequence number for collection being reported **/
|
||||
std::size_t gc_seq_ = 0;
|
||||
/** type of GC that generated this record **/
|
||||
generation upto_;
|
||||
/** #of bytes new allocation **/
|
||||
|
|
@ -181,6 +216,8 @@ namespace xo {
|
|||
std::size_t garbage1_z_ = 0;
|
||||
/** #of bytes garbage from T (i.e. survived 2+ GCs) **/
|
||||
std::size_t garbageN_z_ = 0;
|
||||
/** elapsed time for this GC (see @ref GC::execute_gc) **/
|
||||
nanos dt_;
|
||||
};
|
||||
|
||||
inline std::ostream & operator<< (std::ostream & os, const GcStatisticsHistoryItem & x) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ set(SELF_SRCS
|
|||
)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
xo_dependency(${SELF_LIB} xo_unit)
|
||||
xo_dependency(${SELF_LIB} reflect)
|
||||
xo_dependency(${SELF_LIB} callback)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "GC.hpp"
|
||||
#include "Object.hpp"
|
||||
#include "xo/indentlog/scope.hpp"
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
|
|
@ -1037,9 +1038,9 @@ namespace xo {
|
|||
}
|
||||
|
||||
void
|
||||
GC::cleanup_phase(generation upto)
|
||||
GC::cleanup_phase(generation upto, nanos dt)
|
||||
{
|
||||
scope log(XO_DEBUG(config_.debug_flag_));
|
||||
scope log(XO_DEBUG(config_.stats_flag_));
|
||||
|
||||
std::size_t N0_before_gc = nursery_from()->after_checkpoint();
|
||||
std::size_t N1_before_gc = nursery_from()->before_checkpoint();
|
||||
|
|
@ -1098,6 +1099,7 @@ namespace xo {
|
|||
this->tenured_to()->checkpoint();
|
||||
|
||||
if (log) {
|
||||
log(xtag("gcseq_before_gc", gc_statistics_.n_gc()));
|
||||
log(xtag("N0_before_gc", N0_before_gc));
|
||||
log(xtag("N1_before_gc", N1_before_gc));
|
||||
log(xtag("N_after_gc", N_after_gc));
|
||||
|
|
@ -1107,18 +1109,6 @@ namespace xo {
|
|||
log(xtag("T_after_gc", T_after_gc));
|
||||
}
|
||||
|
||||
GcStatisticsHistoryItem item(upto,
|
||||
new_alloc_z,
|
||||
survive_z,
|
||||
promote_z,
|
||||
persist_z,
|
||||
effort_z,
|
||||
garbage0_z,
|
||||
garbage1_z,
|
||||
garbageN_z);
|
||||
|
||||
this->gc_history_.push_back(item);
|
||||
|
||||
this->incr_gc_pending_ = false;
|
||||
this->gc_statistics_.include_gc(generation::nursery, N0_before_gc, N_before_gc, N_after_gc, promote_z);
|
||||
|
||||
|
|
@ -1129,6 +1119,23 @@ namespace xo {
|
|||
// still want to update tenured stats for current alloc size
|
||||
this->gc_statistics_.update_snapshot(generation::tenured, T_after_gc);
|
||||
}
|
||||
GcStatisticsHistoryItem item(gc_statistics_.n_gc(),
|
||||
upto,
|
||||
new_alloc_z,
|
||||
survive_z,
|
||||
promote_z,
|
||||
persist_z,
|
||||
effort_z,
|
||||
garbage0_z,
|
||||
garbage1_z,
|
||||
garbageN_z,
|
||||
dt);
|
||||
|
||||
log && log(xtag("gcseq_after_gc", gc_statistics_.n_gc()),
|
||||
xtag("item", item));
|
||||
|
||||
this->gc_history_.push_back(item);
|
||||
|
||||
} /*cleanup_phase*/
|
||||
|
||||
void
|
||||
|
|
@ -1136,6 +1143,8 @@ namespace xo {
|
|||
{
|
||||
scope log(XO_DEBUG(config_.stats_flag_));
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
|
||||
bool full_move = (upto == generation::tenured);
|
||||
|
||||
// TODO: RAII version in case of exceptions
|
||||
|
|
@ -1146,9 +1155,7 @@ namespace xo {
|
|||
/* new allocation since last GC */
|
||||
std::size_t new_alloc = this->after_checkpoint();
|
||||
|
||||
++(gc_statistics_.gen_v_[static_cast<std::size_t>(upto)].n_gc_);
|
||||
gc_statistics_.total_allocated_ += new_alloc;
|
||||
gc_statistics_.total_promoted_sab_ = gc_statistics_.total_promoted_;
|
||||
gc_statistics_.begin_gc(upto, new_alloc);
|
||||
|
||||
log && log(xtag("new_alloc", new_alloc));
|
||||
|
||||
|
|
@ -1176,10 +1183,13 @@ namespace xo {
|
|||
|
||||
log && log("step 6 : cleanup");
|
||||
|
||||
this->cleanup_phase(upto);
|
||||
|
||||
this->capture_object_statistics(upto, capture_phase::sae);
|
||||
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
auto dt = std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0);
|
||||
|
||||
this->cleanup_phase(upto, xo::qty::qty::nanoseconds(dt.count()));
|
||||
|
||||
log && log("object statistics [nursery]:");
|
||||
log && log(refrtag("stats", object_statistics_sab_[gen2int(generation::nursery)]));
|
||||
log && log("object statistics [tenured]:");
|
||||
|
|
@ -1233,6 +1243,13 @@ namespace xo {
|
|||
this->request_gc(full_gc_pending_ ? generation::tenured : generation::nursery);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GC::enable_gc_once() {
|
||||
this->enable_gc();
|
||||
this->disable_gc();
|
||||
}
|
||||
|
||||
} /*namespace gc*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace xo {
|
|||
{
|
||||
this->update_snapshot(after_z);
|
||||
|
||||
//++n_gc_;
|
||||
new_alloc_z_ += alloc_z;
|
||||
scanned_z_ += before_z;
|
||||
survive_z_ += after_z;
|
||||
|
|
@ -41,6 +42,15 @@ namespace xo {
|
|||
<< ">";
|
||||
}
|
||||
|
||||
void
|
||||
GcStatistics::begin_gc(generation upto,
|
||||
std::size_t new_alloc)
|
||||
{
|
||||
++(this->gen_v_[static_cast<std::size_t>(upto)].n_gc_);
|
||||
this->total_allocated_ += new_alloc;
|
||||
this->total_promoted_sab_ = total_promoted_;
|
||||
}
|
||||
|
||||
void
|
||||
GcStatistics::include_gc(generation upto,
|
||||
std::size_t alloc_z,
|
||||
|
|
@ -105,6 +115,7 @@ namespace xo {
|
|||
<< xrtag("garbage0_z", garbage0_z_)
|
||||
<< xrtag("garbage1_z", garbage1_z_)
|
||||
<< xrtag("garbageN_z", garbageN_z_)
|
||||
<< xrtag("dt", dt_)
|
||||
<< ">";
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +188,8 @@ namespace xo {
|
|||
refrtag("effort_z", x.effort_z_),
|
||||
refrtag("garbage0_z", x.garbage0_z_),
|
||||
refrtag("garbage1_z", x.garbage1_z_),
|
||||
refrtag("garbageN_z", x.garbageN_z_));
|
||||
refrtag("garbageN_z", x.garbageN_z_),
|
||||
refrtag("dt", x.dt_));
|
||||
}
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -58,5 +58,6 @@ if (XO_ENABLE_EXAMPLES)
|
|||
|
||||
xo_dependency(${SELF_EXE} xo_object)
|
||||
xo_dependency(${SELF_EXE} randomgen)
|
||||
xo_dependency(${SELF_EXE} xo_flatstring)
|
||||
xo_dependency(${SELF_EXE} xo_alloc)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "xo/randomgen/xoshiro256.hpp"
|
||||
#include "xo/randomgen/random_seed.hpp"
|
||||
#include "xo/object/Integer.hpp"
|
||||
#include "xo/flatstring/flatstring.hpp"
|
||||
#include "xo/indentlog/scope.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
|
|
@ -37,6 +38,10 @@ struct ImRect {
|
|||
ImRect() = default;
|
||||
ImRect(const ImVec2 & tl, const ImVec2 & br) : top_left_{tl}, bottom_right_{br} {}
|
||||
|
||||
static ImRect from_xy_span(const ImVec2 & x_span, const ImVec2 & y_span) {
|
||||
return ImRect(ImVec2{x_span.x, y_span.x}, ImVec2{x_span.y, y_span.y});
|
||||
}
|
||||
|
||||
std::pair<float, float> x_span() const { return std::make_pair(top_left_.x, bottom_right_.x); }
|
||||
std::pair<float, float> y_span() const { return std::make_pair(top_left_.y, bottom_right_.y); }
|
||||
|
||||
|
|
@ -315,6 +320,21 @@ draw_filled_rect_with_label(const char * text,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_filled_rect(const char * tooltip,
|
||||
const ImRect & rect,
|
||||
ImU32 fillcolor,
|
||||
ImDrawList * draw_list)
|
||||
{
|
||||
draw_filled_rect_with_label(nullptr,
|
||||
tooltip,
|
||||
rect,
|
||||
fillcolor,
|
||||
IM_COL32(255, 255, 255, 255),
|
||||
draw_list);
|
||||
}
|
||||
|
||||
|
||||
using xo::scope;
|
||||
|
||||
/**
|
||||
|
|
@ -582,6 +602,93 @@ using xo::gc::GcStatisticsHistoryItem;
|
|||
using xo::xtag;
|
||||
using std::size_t;
|
||||
|
||||
/** for history tooltip, choose which statistic to headline **/
|
||||
enum class gc_history_headline {
|
||||
survive,
|
||||
promote,
|
||||
persist,
|
||||
garbage0,
|
||||
garbage1,
|
||||
garbageN,
|
||||
N
|
||||
};
|
||||
|
||||
xo::flatstring<256>
|
||||
write_gc_history_tooltip(gc_history_headline headline,
|
||||
const GcStatisticsHistoryItem & stats)
|
||||
{
|
||||
xo::flatstring<256> retval;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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",
|
||||
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()
|
||||
);
|
||||
|
||||
return retval.ensure_final_null();
|
||||
}
|
||||
|
||||
/** @param gen if @ref generation::nursery, only display nursery collections.
|
||||
* otherwise display both
|
||||
**/
|
||||
void
|
||||
draw_gc_history(const GcStateDescription & gcstate,
|
||||
generation gen,
|
||||
|
|
@ -592,7 +699,7 @@ draw_gc_history(const GcStateDescription & gcstate,
|
|||
{
|
||||
scope log(XO_DEBUG(debug_flag));
|
||||
|
||||
float lm = 50;
|
||||
float lm = 10;
|
||||
float tm = 25;
|
||||
|
||||
/* we're going to make a bar chart */
|
||||
|
|
@ -607,18 +714,24 @@ draw_gc_history(const GcStateDescription & gcstate,
|
|||
|
||||
/* 1st loop: figure out max y scale */
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history) {
|
||||
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 ((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 (yplus_scale < sz + pz + psz)
|
||||
yplus_scale = sz + pz + psz;
|
||||
|
||||
if (yminus_scale < g0z + g1z + gNz)
|
||||
yminus_scale = g0z + g1z + gNz;
|
||||
if (yminus_scale < g0z + g1z + gNz)
|
||||
yminus_scale = g0z + g1z + gNz;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* y-coord of x-axis */
|
||||
|
|
@ -631,58 +744,124 @@ draw_gc_history(const GcStateDescription & gcstate,
|
|||
|
||||
/* 2nd loop: draw bars */
|
||||
std::size_t i = 0;
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history) {
|
||||
/* x-coordinates of bar */
|
||||
float x_lo = lm + i * bar_w;
|
||||
float x_hi = x_lo + bar_w - 1;
|
||||
for (const GcStatisticsHistoryItem & stats : gc_history)
|
||||
{
|
||||
if ((gen == stats.upto_) || (gen == generation::tenured))
|
||||
{
|
||||
/*
|
||||
* ys_lo +--+
|
||||
* | | survive_z (survived 1st GC)
|
||||
* | |
|
||||
* yp_lo +--+
|
||||
* | | promote_z (sruvived 2nd GC)
|
||||
* | |
|
||||
* ypsz_lo +--+
|
||||
* | | persist_z (survived 3+ GCs)
|
||||
* | |
|
||||
* y_zero +--+
|
||||
* | | gN (killed on 3+ GC)
|
||||
* | |
|
||||
* ygN_hi +--+
|
||||
* | | g1 (killed on 2nd GC)
|
||||
* | |
|
||||
* yg1_hi +--+
|
||||
* | | g0 (killed on 1st GC)
|
||||
* | |
|
||||
* yg0_hi +--+
|
||||
*/
|
||||
|
||||
/* y-coordinates of persist bar (survived 3+ GCs) */
|
||||
float ypsz_lo = (y_zero
|
||||
- (display_h * stats.persist_z_ / y_scale));
|
||||
ImU32 persist_color = IM_COL32( 0, 64, 192, 255); /*darker blue*/
|
||||
ImU32 promote_color = IM_COL32( 0, 128, 0, 255); /*darker green*/
|
||||
ImU32 survive_color = IM_COL32( 32, 192, 32, 255); /*lighter green*/
|
||||
ImU32 garbageN_color = IM_COL32(255, 128, 64, 255); /*darker orange*/
|
||||
ImU32 garbage1_color = IM_COL32(255, 192, 128, 255); /*medium orange*/
|
||||
ImU32 garbage0_color = IM_COL32(255, 255, 192, 255); /*pale yellow*/
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, ypsz_lo), ImVec2(x_hi, y_zero),
|
||||
IM_COL32( 0, 64, 192, 255) /*darker blue*/);
|
||||
/* x-coordinates of bar */
|
||||
float x_lo = bounding_rect.x_lo() + lm + i * bar_w;
|
||||
float x_hi = x_lo + bar_w - 1;
|
||||
ImVec2 x_span{x_lo, x_hi};
|
||||
|
||||
/* 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));
|
||||
/* y-coordinates of persist bar (survived 3+ GCs) */
|
||||
float ypsz_lo = (y_zero
|
||||
- (display_h * stats.persist_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<256> tt = write_gc_history_tooltip(gc_history_headline::persist, stats);
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, yp_lo), ImVec2(x_hi, yp_hi),
|
||||
IM_COL32( 0, 128, 0, 255) /*darker green*/);
|
||||
draw_filled_rect(tt.c_str(),
|
||||
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<256> tt = write_gc_history_tooltip(gc_history_headline::promote, stats);
|
||||
|
||||
/* 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));
|
||||
draw_filled_rect(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(yp_lo, yp_hi)),
|
||||
promote_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, ys_lo), ImVec2(x_hi, ys_hi),
|
||||
IM_COL32( 32, 192, 32, 255));
|
||||
/* 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<256> tt = write_gc_history_tooltip(gc_history_headline::survive, stats);
|
||||
|
||||
// -----------------------------------------------------------
|
||||
draw_filled_rect(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ys_lo, ys_hi)),
|
||||
survive_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
/* y-coordinates of garbageN bar (killed on 3+ GC) */
|
||||
float ygN_lo = y_zero;
|
||||
float ygN_hi = (y_zero
|
||||
+ (display_h * stats.garbageN_z_ / y_scale));
|
||||
// -----------------------------------------------------------
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, ygN_lo), ImVec2(x_hi, ygN_hi),
|
||||
IM_COL32(255, 192, 32, 255));
|
||||
/* y-coordinates of garbageN bar (killed on 3+ GC) */
|
||||
float ygN_lo = y_zero;
|
||||
float ygN_hi = (y_zero
|
||||
+ (display_h * stats.garbageN_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<256> tt = write_gc_history_tooltip(gc_history_headline::garbageN, stats);
|
||||
|
||||
/* y-coordinates of garbage1 bar (killed on 2nd GC) */
|
||||
float yg1_lo = ygN_hi;
|
||||
float yg1_hi = (yg1_lo
|
||||
+ (display_h * stats.garbage1_z_ / y_scale));
|
||||
draw_filled_rect(tt.c_str(),
|
||||
ImRect::from_xy_span(x_span, ImVec2(ygN_lo, ygN_hi)),
|
||||
garbageN_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, y_zero), ImVec2(x_hi, yg1_hi),
|
||||
IM_COL32(192, 192, 32, 255));
|
||||
/* y-coordinates of garbage1 bar (killed on 2nd GC) */
|
||||
float yg1_lo = ygN_hi;
|
||||
float yg1_hi = (yg1_lo
|
||||
+ (display_h * stats.garbage1_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<256> tt = write_gc_history_tooltip(gc_history_headline::garbage1, stats);
|
||||
|
||||
/* y-coordinates of garbage0 bar (killed on 1st GC) */
|
||||
float yg0_lo = yg1_hi;
|
||||
float yg0_hi = (yg0_hi
|
||||
+ (display_h * stats.garbage0_z_ / y_scale));
|
||||
draw_filled_rect(tt.c_str(),
|
||||
ImRect(ImVec2(x_lo, yg1_lo), ImVec2(x_hi, yg1_hi)),
|
||||
garbage1_color,
|
||||
draw_list);
|
||||
}
|
||||
|
||||
draw_list->AddRectFilled(ImVec2(x_lo, yg0_lo), ImVec2(x_hi, yg0_hi),
|
||||
IM_COL32(255, 255, 32, 255));
|
||||
/* y-coordinates of garbage0 bar (killed on 1st GC) */
|
||||
float yg0_lo = yg1_hi;
|
||||
float yg0_hi = (yg0_lo
|
||||
+ (display_h * stats.garbage0_z_ / y_scale));
|
||||
{
|
||||
xo::flatstring<256> tt = write_gc_history_tooltip(gc_history_headline::garbage0, stats);
|
||||
|
||||
draw_filled_rect(tt.c_str(),
|
||||
ImRect(ImVec2(x_lo, yg0_lo), ImVec2(x_hi, yg0_hi)),
|
||||
garbage0_color,
|
||||
draw_list);
|
||||
}
|
||||
} else {
|
||||
/* draw nothing */
|
||||
;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
|
@ -791,6 +970,7 @@ draw_gc_state(const AppState & app_state,
|
|||
nullptr,
|
||||
nullptr);
|
||||
|
||||
/* just incremental (nursery) collections */
|
||||
draw_gc_history(gcstate,
|
||||
generation::nursery,
|
||||
app_state.gc_->gc_history(),
|
||||
|
|
@ -799,6 +979,15 @@ draw_gc_state(const AppState & app_state,
|
|||
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));
|
||||
|
|
@ -1004,7 +1193,7 @@ int main(int, char **)
|
|||
0x0020, 0x00ff, // basic latin + latin supplement
|
||||
0x0100, 0x017f, // latin extended-A
|
||||
0x0180, 0x024f, // latin extended-B
|
||||
0x2080, 0x208a, // subscript numerals
|
||||
0x2080, 0x2099, // subscript numerals + letters through n
|
||||
0x25b2, 0x25b4, // arrows
|
||||
0,
|
||||
};
|
||||
|
|
@ -1116,7 +1305,7 @@ int main(int, char **)
|
|||
if (ImGui::Button("Button"))
|
||||
++counter;
|
||||
ImGui::NewLine(); // ImGui::SameLine()
|
||||
/* \u2080 = N0, \u2081 = N1 */
|
||||
/* N\u2080 = N0, N\u2081 = N1 */
|
||||
ImGui::Text("alloc [%lu] avail [%lu] ",
|
||||
gcstate.gc_allocated_,
|
||||
gcstate.gc_available_);
|
||||
|
|
@ -1148,11 +1337,10 @@ int main(int, char **)
|
|||
draw_list,
|
||||
&draw_state.gcw_nursery_alloc_rect_);
|
||||
|
||||
app_state.gc_->enable_gc();
|
||||
/* GC may run here, in which case control reenters via AnimateGcCopyCb;
|
||||
* callback will rely on loop assignments to draw_area members.
|
||||
*/
|
||||
app_state.gc_->disable_gc();
|
||||
app_state.gc_->enable_gc_once();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue