From 0ffbba3365dbff7c1d26875330cf87516776da23 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 27 Feb 2021 18:54:03 -0500 Subject: [PATCH] restore stashed stats for closing banner #1374 --- include/notcurses/notcurses.h | 2 + src/lib/internal.h | 1 + src/lib/notcurses.c | 135 +++++++++++++++++++++++----------- 3 files changed, 96 insertions(+), 42 deletions(-) diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index ac44456b5..f0c6a6ba7 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1238,6 +1238,8 @@ API bool notcurses_canpixel(const struct notcurses* nc); // Must not be called concurrently with either input or rasterization. API int notcurses_check_pixel_support(struct notcurses* nc); +// whenever a new field is added here, ensure we add the proper rule to +// notcurses_stats_reset(), so that values are preserved in the stash stats. typedef struct ncstats { // purely increasing stats uint64_t renders; // successful ncpile_render() runs diff --git a/src/lib/internal.h b/src/lib/internal.h index 1bf49cc7f..60646ac00 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -359,6 +359,7 @@ typedef struct notcurses { pthread_mutex_t statlock; ncstats stats; // some statistics across the lifetime of the notcurses ctx + ncstats stashed_stats; // retain across a notcurses_stats_reset(), to print in closing banner FILE* ttyfp; // FILE* for writing rasterized data int ttyfd; // file descriptor for controlling tty diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index bfb50089e..061e59c29 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -735,6 +735,52 @@ void notcurses_stats_reset(notcurses* nc, ncstats* stats){ if(stats){ memcpy(stats, &nc->stats, sizeof(*stats)); } + // add the stats to the stashed stats, so that we can show true totals on + // shutdown in the closing banner + ncstats* stash = &nc->stashed_stats; + if(nc->stats.render_min_ns < stash->render_min_ns){ + stash->render_min_ns = nc->stats.render_min_ns; + } + if(nc->stats.render_min_bytes < stash->render_min_bytes){ + stash->render_min_bytes = nc->stats.render_min_bytes; + } + if(nc->stats.raster_min_ns < stash->raster_min_ns){ + stash->raster_min_ns = nc->stats.raster_min_ns; + } + if(nc->stats.writeout_min_ns < stash->writeout_min_ns){ + stash->writeout_min_ns = nc->stats.writeout_min_ns; + } + if(nc->stats.render_max_ns > stash->render_max_ns){ + stash->render_max_ns = nc->stats.render_max_ns; + } + if(nc->stats.render_max_bytes > stash->render_max_bytes){ + stash->render_max_bytes = nc->stats.render_max_bytes; + } + if(nc->stats.raster_max_ns > stash->raster_max_ns){ + stash->raster_max_ns = nc->stats.raster_max_ns; + } + if(nc->stats.writeout_max_ns > stash->writeout_max_ns){ + stash->writeout_max_ns = nc->stats.writeout_max_ns; + } + stash->writeout_ns += nc->stats.writeout_ns; + stash->raster_ns += nc->stats.raster_ns; + stash->render_ns += nc->stats.render_ns; + stash->render_bytes += nc->stats.render_bytes; + stash->failed_renders += nc->stats.failed_renders; + stash->failed_writeouts += nc->stats.failed_writeouts; + stash->renders += nc->stats.renders; + stash->writeouts += nc->stats.writeouts; + stash->cellelisions += nc->stats.cellelisions; + stash->cellemissions += nc->stats.cellemissions; + stash->fgelisions += nc->stats.fgelisions; + stash->fgemissions += nc->stats.fgemissions; + stash->bgelisions += nc->stats.bgelisions; + stash->bgemissions += nc->stats.bgemissions; + stash->defaultelisions += nc->stats.defaultelisions; + stash->defaultemissions += nc->stats.defaultemissions; + stash->refreshes = nc->stats.refreshes; + stash->fbbytes = nc->stats.fbbytes; + stash->planes = nc->stats.planes; reset_stats(&nc->stats); pthread_mutex_unlock(&nc->statlock); } @@ -959,7 +1005,9 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){ ret->margin_r = opts->margin_r; ret->cursory = ret->cursorx = -1; memset(&ret->stats, 0, sizeof(ret->stats)); + memset(&ret->stashed_stats, 0, sizeof(ret->stashed_stats)); reset_stats(&ret->stats); + reset_stats(&ret->stashed_stats); ret->ttyfp = outfp; ret->renderfp = opts->renderfp; memset(&ret->rstate, 0, sizeof(ret->rstate)); @@ -1152,66 +1200,69 @@ int notcurses_stop(notcurses* nc){ free(nc->lastframe); free(nc->rstate.mstream); input_free_esctrie(&nc->input.inputescapes); + // get any current stats loaded into stash_stats + notcurses_stats_reset(nc, NULL); if(!nc->suppress_banner){ - if(nc->stats.renders){ + const ncstats *stats = &nc->stashed_stats; + if(stats->renders){ char totalbuf[BPREFIXSTRLEN + 1]; char minbuf[BPREFIXSTRLEN + 1]; char maxbuf[BPREFIXSTRLEN + 1]; char avgbuf[BPREFIXSTRLEN + 1]; - qprefix(nc->stats.render_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(nc->stats.render_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(nc->stats.render_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(nc->stats.render_ns / nc->stats.renders, NANOSECS_IN_SEC, avgbuf, 0); + qprefix(stats->render_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->render_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->render_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->render_ns / stats->renders, NANOSECS_IN_SEC, avgbuf, 0); fprintf(stderr, "\n%ju render%s, %ss (%ss min, %ss avg, %ss max)\n", - nc->stats.renders, nc->stats.renders == 1 ? "" : "s", + stats->renders, stats->renders == 1 ? "" : "s", totalbuf, minbuf, avgbuf, maxbuf); - qprefix(nc->stats.raster_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(nc->stats.raster_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(nc->stats.raster_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(nc->stats.raster_ns / nc->stats.writeouts, NANOSECS_IN_SEC, avgbuf, 0); + qprefix(stats->raster_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->raster_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->raster_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->raster_ns / stats->writeouts, NANOSECS_IN_SEC, avgbuf, 0); fprintf(stderr, "%ju raster%s, %ss (%ss min, %ss avg, %ss max)\n", - nc->stats.writeouts, nc->stats.writeouts == 1 ? "" : "s", + stats->writeouts, stats->writeouts == 1 ? "" : "s", totalbuf, minbuf, avgbuf, maxbuf); - qprefix(nc->stats.writeout_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(nc->stats.writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(nc->stats.writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(nc->stats.writeouts ? nc->stats.writeout_ns / nc->stats.writeouts : 0, + qprefix(stats->writeout_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->writeouts ? stats->writeout_ns / stats->writeouts : 0, NANOSECS_IN_SEC, avgbuf, 0); fprintf(stderr, "%ju write%s, %ss (%ss min, %ss avg, %ss max)\n", - nc->stats.writeouts, nc->stats.writeouts == 1 ? "" : "s", + stats->writeouts, stats->writeouts == 1 ? "" : "s", totalbuf, minbuf, avgbuf, maxbuf); - bprefix(nc->stats.render_bytes, 1, totalbuf, 1), - bprefix(nc->stats.render_min_bytes, 1, minbuf, 1), - bprefix(nc->stats.renders ? nc->stats.render_bytes / nc->stats.renders : 0, 1, avgbuf, 1); - bprefix(nc->stats.render_max_bytes, 1, maxbuf, 1), + bprefix(stats->render_bytes, 1, totalbuf, 1), + bprefix(stats->render_min_bytes, 1, minbuf, 1), + bprefix(stats->renders ? stats->render_bytes / stats->renders : 0, 1, avgbuf, 1); + bprefix(stats->render_max_bytes, 1, maxbuf, 1), fprintf(stderr, "%sB (%sB min, %sB avg, %sB max)\n", totalbuf, minbuf, avgbuf, maxbuf); } - if(nc->stats.renders || nc->stats.failed_renders){ + if(stats->renders || stats->failed_renders){ fprintf(stderr, "%ju failed render%s, %ju failed write%s, %ju refresh%s\n", - nc->stats.failed_renders, - nc->stats.failed_renders == 1 ? "" : "s", - nc->stats.failed_writeouts, - nc->stats.failed_writeouts == 1 ? "" : "s", - nc->stats.refreshes, - nc->stats.refreshes == 1 ? "" : "es"); + stats->failed_renders, + stats->failed_renders == 1 ? "" : "s", + stats->failed_writeouts, + stats->failed_writeouts == 1 ? "" : "s", + stats->refreshes, + stats->refreshes == 1 ? "" : "es"); fprintf(stderr, "RGB emits:elides: def %ju:%ju fg %ju:%ju bg %ju:%ju\n", - nc->stats.defaultemissions, - nc->stats.defaultelisions, - nc->stats.fgemissions, - nc->stats.fgelisions, - nc->stats.bgemissions, - nc->stats.bgelisions); + stats->defaultemissions, + stats->defaultelisions, + stats->fgemissions, + stats->fgelisions, + stats->bgemissions, + stats->bgelisions); fprintf(stderr, "Cell emits:elides: %ju/%ju (%.2f%%) %.2f%% %.2f%% %.2f%%\n", - nc->stats.cellemissions, nc->stats.cellelisions, - (nc->stats.cellemissions + nc->stats.cellelisions) == 0 ? 0 : - (nc->stats.cellelisions * 100.0) / (nc->stats.cellemissions + nc->stats.cellelisions), - (nc->stats.defaultemissions + nc->stats.defaultelisions) == 0 ? 0 : - (nc->stats.defaultelisions * 100.0) / (nc->stats.defaultemissions + nc->stats.defaultelisions), - (nc->stats.fgemissions + nc->stats.fgelisions) == 0 ? 0 : - (nc->stats.fgelisions * 100.0) / (nc->stats.fgemissions + nc->stats.fgelisions), - (nc->stats.bgemissions + nc->stats.bgelisions) == 0 ? 0 : - (nc->stats.bgelisions * 100.0) / (nc->stats.bgemissions + nc->stats.bgelisions)); + stats->cellemissions, stats->cellelisions, + (stats->cellemissions + stats->cellelisions) == 0 ? 0 : + (stats->cellelisions * 100.0) / (stats->cellemissions + stats->cellelisions), + (stats->defaultemissions + stats->defaultelisions) == 0 ? 0 : + (stats->defaultelisions * 100.0) / (stats->defaultemissions + stats->defaultelisions), + (stats->fgemissions + stats->fgelisions) == 0 ? 0 : + (stats->fgelisions * 100.0) / (stats->fgemissions + stats->fgelisions), + (stats->bgemissions + stats->bgelisions) == 0 ? 0 : + (stats->bgelisions * 100.0) / (stats->bgemissions + stats->bgelisions)); } } del_curterm(cur_term);