mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
add raster timing stats #1324
This commit is contained in:
parent
d47337c4ae
commit
43dd0440f7
5
USAGE.md
5
USAGE.md
@ -3018,9 +3018,12 @@ typedef struct ncstats {
|
|||||||
uint64_t render_bytes; // bytes emitted to ttyfp
|
uint64_t render_bytes; // bytes emitted to ttyfp
|
||||||
int64_t render_max_bytes; // max bytes emitted for a frame
|
int64_t render_max_bytes; // max bytes emitted for a frame
|
||||||
int64_t render_min_bytes; // min bytes emitted for a frame
|
int64_t render_min_bytes; // min bytes emitted for a frame
|
||||||
uint64_t render_ns; // nanoseconds spent in render+raster
|
uint64_t render_ns; // nanoseconds spent rendering
|
||||||
int64_t render_max_ns; // max ns spent in render+raster for a frame
|
int64_t render_max_ns; // max ns spent in render+raster for a frame
|
||||||
int64_t render_min_ns; // min ns spent in render+raster for a frame
|
int64_t render_min_ns; // min ns spent in render+raster for a frame
|
||||||
|
uint64_t raster_ns; // nanoseconds spent rasterizing
|
||||||
|
int64_t raster_max_ns; // max ns spent in raster for a frame
|
||||||
|
int64_t raster_min_ns; // min ns spent in raster for a frame
|
||||||
uint64_t writeout_ns; // nanoseconds spent writing frames to terminal
|
uint64_t writeout_ns; // nanoseconds spent writing frames to terminal
|
||||||
int64_t writeout_max_ns; // max ns spent writing out a frame
|
int64_t writeout_max_ns; // max ns spent writing out a frame
|
||||||
int64_t writeout_min_ns; // min ns spent writing out a frame
|
int64_t writeout_min_ns; // min ns spent writing out a frame
|
||||||
|
@ -20,9 +20,12 @@ typedef struct ncstats {
|
|||||||
uint64_t render_bytes; // bytes emitted to ttyfp
|
uint64_t render_bytes; // bytes emitted to ttyfp
|
||||||
int64_t render_max_bytes; // max bytes emitted for a frame
|
int64_t render_max_bytes; // max bytes emitted for a frame
|
||||||
int64_t render_min_bytes; // min bytes emitted for a frame
|
int64_t render_min_bytes; // min bytes emitted for a frame
|
||||||
uint64_t render_ns; // nanoseconds spent in render+raster
|
uint64_t render_ns; // nanoseconds spent rendering
|
||||||
int64_t render_max_ns; // max ns spent for a frame
|
int64_t render_max_ns; // max ns spent for a frame
|
||||||
int64_t render_min_ns; // min ns spent for a frame
|
int64_t render_min_ns; // min ns spent for a frame
|
||||||
|
uint64_t raster_ns; // nanoseconds spent rasterizing
|
||||||
|
int64_t raster_max_ns; // max ns spent in raster for a frame
|
||||||
|
int64_t raster_min_ns; // min ns spent in raster for a frame
|
||||||
uint64_t writeout_ns; // ns spent writing frames to terminal
|
uint64_t writeout_ns; // ns spent writing frames to terminal
|
||||||
int64_t writeout_max_ns; // max ns spent writing out a frame
|
int64_t writeout_max_ns; // max ns spent writing out a frame
|
||||||
int64_t writeout_min_ns; // min ns spent writing out a frame
|
int64_t writeout_min_ns; // min ns spent writing out a frame
|
||||||
@ -73,15 +76,19 @@ existing terminal state. As a first approximation, the time a terminal takes to
|
|||||||
ingest and reflect a frame is dependent on the size of the rasterized frame.
|
ingest and reflect a frame is dependent on the size of the rasterized frame.
|
||||||
|
|
||||||
**render_ns**, **render_max_ns**, and **render_min_ns** track the total
|
**render_ns**, **render_max_ns**, and **render_min_ns** track the total
|
||||||
amount of time spent rendering and rasterizing frames in nanoseconds. Rendering
|
amount of time spent rendering frames in nanoseconds. Rendering
|
||||||
and rasterizing takes place in **notcurses_render(3)**, and is the entirety of
|
takes place in **ncpile_render** (called by **notcurses_render(3)** and
|
||||||
**notcurses_render_to_buffer(3)**. These steps are independent of the terminal.
|
**notcurses_render_to_buffer**). This step is independent of the terminal.
|
||||||
|
|
||||||
|
**raster_ns**, **raster_max_ns**, and **raster_min_ns** track the total
|
||||||
|
amount of time spent rasterizing frames in nanoseconds. Rasterizing
|
||||||
|
takes place in **ncpile_raster** (called by **notcurses_raster(3)** and
|
||||||
|
**notcurses_render_to_buffer**). This step depends on the terminal definitions.
|
||||||
|
The same frame might not rasterize to the same bytes for different terminals.
|
||||||
|
|
||||||
**writeout_ns**, **writeout_max_ns**, and **writeout_min_ns** track the total
|
**writeout_ns**, **writeout_max_ns**, and **writeout_min_ns** track the total
|
||||||
amount of time spent writing frames to the terminal. This takes place in only
|
amount of time spent writing frames to the terminal. This takes place in
|
||||||
**notcurses_render(3)**. If **notcurses_render_to_buffer(3)** is used, the
|
**ncpile_rasterize** (called by **notcurses_render(3)**).
|
||||||
user is responsible for writing out the frame, and it will not be tracked by
|
|
||||||
any stat.
|
|
||||||
|
|
||||||
**cellemissions** reflects the number of EGCs written to the terminal.
|
**cellemissions** reflects the number of EGCs written to the terminal.
|
||||||
**cellelisions** reflects the number of cells which were not written, due to
|
**cellelisions** reflects the number of cells which were not written, due to
|
||||||
|
@ -620,7 +620,7 @@ typedef struct nccell {
|
|||||||
uint64_t channels; // + 8B == 16B
|
uint64_t channels; // + 8B == 16B
|
||||||
} nccell;
|
} nccell;
|
||||||
|
|
||||||
typedef nccell cell; // FIXME backwards-compat, remove in 3.0
|
typedef nccell cell; // FIXME backwards-compat, remove in ABI3
|
||||||
|
|
||||||
#define CELL_TRIVIAL_INITIALIZER { .gcluster = 0, .gcluster_backstop = 0, .width = 0, .stylemask = 0, .channels = 0, }
|
#define CELL_TRIVIAL_INITIALIZER { .gcluster = 0, .gcluster_backstop = 0, .width = 0, .stylemask = 0, .channels = 0, }
|
||||||
// do *not* load invalid EGCs using these macros! there is no way for us to
|
// do *not* load invalid EGCs using these macros! there is no way for us to
|
||||||
@ -1137,8 +1137,8 @@ API struct ncplane* ncplane_create(struct ncplane* n, const ncplane_options* nop
|
|||||||
// be the top, bottom, and root of this new pile.
|
// be the top, bottom, and root of this new pile.
|
||||||
API struct ncplane* ncpile_create(struct notcurses* nc, const ncplane_options* nopts);
|
API struct ncplane* ncpile_create(struct notcurses* nc, const ncplane_options* nopts);
|
||||||
|
|
||||||
// This function will be removed in 3.0 in favor of ncplane_create().
|
// This function will be removed in ABI3 in favor of ncplane_create().
|
||||||
// It persists in 2.0 only for backwards compatibility.
|
// It persists in ABI2 only for backwards compatibility.
|
||||||
API struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, int x, void* opaque, const char* name)
|
API struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, int x, void* opaque, const char* name)
|
||||||
__attribute__ ((deprecated));
|
__attribute__ ((deprecated));
|
||||||
|
|
||||||
@ -1237,12 +1237,13 @@ typedef struct ncstats {
|
|||||||
uint64_t writeouts; // successful ncpile_rasterize() runs
|
uint64_t writeouts; // successful ncpile_rasterize() runs
|
||||||
uint64_t failed_renders; // aborted renders, should be 0
|
uint64_t failed_renders; // aborted renders, should be 0
|
||||||
uint64_t failed_writeouts; // aborted writes
|
uint64_t failed_writeouts; // aborted writes
|
||||||
|
// FIXME these next three all ought be "writeout" or "raster"
|
||||||
uint64_t render_bytes; // bytes emitted to ttyfp
|
uint64_t render_bytes; // bytes emitted to ttyfp
|
||||||
int64_t render_max_bytes; // max bytes emitted for a frame
|
int64_t render_max_bytes; // max bytes emitted for a frame
|
||||||
int64_t render_min_bytes; // min bytes emitted for a frame
|
int64_t render_min_bytes; // min bytes emitted for a frame
|
||||||
uint64_t render_ns; // nanoseconds spent in render+raster
|
uint64_t render_ns; // nanoseconds spent rendering
|
||||||
int64_t render_max_ns; // max ns spent in render+raster for a frame
|
int64_t render_max_ns; // max ns spent in render for a frame
|
||||||
int64_t render_min_ns; // min ns spent in render+raster for a frame
|
int64_t render_min_ns; // min ns spent in render for a frame
|
||||||
uint64_t writeout_ns; // nanoseconds spent writing frames to terminal
|
uint64_t writeout_ns; // nanoseconds spent writing frames to terminal
|
||||||
int64_t writeout_max_ns; // max ns spent writing out a frame
|
int64_t writeout_max_ns; // max ns spent writing out a frame
|
||||||
int64_t writeout_min_ns; // min ns spent writing out a frame
|
int64_t writeout_min_ns; // min ns spent writing out a frame
|
||||||
@ -1259,6 +1260,11 @@ typedef struct ncstats {
|
|||||||
// current state -- these can decrease
|
// current state -- these can decrease
|
||||||
uint64_t fbbytes; // total bytes devoted to all active framebuffers
|
uint64_t fbbytes; // total bytes devoted to all active framebuffers
|
||||||
unsigned planes; // number of planes currently in existence
|
unsigned planes; // number of planes currently in existence
|
||||||
|
|
||||||
|
// FIXME placed here for ABI compatibility; move up for ABI3
|
||||||
|
uint64_t raster_ns; // nanoseconds spent rasterizing
|
||||||
|
int64_t raster_max_ns; // max ns spent in raster for a frame
|
||||||
|
int64_t raster_min_ns; // min ns spent in raster for a frame
|
||||||
} ncstats;
|
} ncstats;
|
||||||
|
|
||||||
// Allocate an ncstats object. Use this rather than allocating your own, since
|
// Allocate an ncstats object. Use this rather than allocating your own, since
|
||||||
|
@ -412,20 +412,18 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
|
|||||||
table_segment(nc, " runtime", "│");
|
table_segment(nc, " runtime", "│");
|
||||||
table_segment(nc, " frames", "│");
|
table_segment(nc, " frames", "│");
|
||||||
table_segment(nc, "output(B)", "│");
|
table_segment(nc, "output(B)", "│");
|
||||||
table_segment(nc, "rendering", "│");
|
|
||||||
table_segment(nc, " FPS", "│");
|
table_segment(nc, " FPS", "│");
|
||||||
table_segment(nc, "%r", "│");
|
table_segment(nc, "%r", "│");
|
||||||
|
table_segment(nc, "%a", "│");
|
||||||
table_segment(nc, "%w", "│");
|
table_segment(nc, "%w", "│");
|
||||||
table_segment(nc, "TheoFPS", "║\n══╤════════╤════════╪═══════╪═════════╪═════════╪═══════╪══╪══╪═══════╣\n");
|
table_segment(nc, "TheoFPS", "║\n══╤════════╤════════╪═══════╪═════════╪═══════╪══╪══╪══╪═══════╣\n");
|
||||||
char timebuf[PREFIXSTRLEN + 1];
|
char timebuf[PREFIXSTRLEN + 1];
|
||||||
char tfpsbuf[PREFIXSTRLEN + 1];
|
char tfpsbuf[PREFIXSTRLEN + 1];
|
||||||
char totalbuf[BPREFIXSTRLEN + 1];
|
char totalbuf[BPREFIXSTRLEN + 1];
|
||||||
char rtimebuf[PREFIXSTRLEN + 1];
|
|
||||||
uint64_t nsdelta = 0;
|
uint64_t nsdelta = 0;
|
||||||
for(size_t i = 0 ; i < strlen(spec) ; ++i){
|
for(size_t i = 0 ; i < strlen(spec) ; ++i){
|
||||||
nsdelta += results[i].timens;
|
nsdelta += results[i].timens;
|
||||||
qprefix(results[i].timens, NANOSECS_IN_SEC, timebuf, 0);
|
qprefix(results[i].timens, NANOSECS_IN_SEC, timebuf, 0);
|
||||||
qprefix(results[i].stats.render_ns, NANOSECS_IN_SEC, rtimebuf, 0);
|
|
||||||
bprefix(results[i].stats.render_bytes, 1, totalbuf, 0);
|
bprefix(results[i].stats.render_bytes, 1, totalbuf, 0);
|
||||||
if(results[i].stats.renders){
|
if(results[i].stats.renders){
|
||||||
qprefix((uintmax_t)results[i].stats.renders * NANOSECS_IN_SEC * 1000 /
|
qprefix((uintmax_t)results[i].stats.renders * NANOSECS_IN_SEC * 1000 /
|
||||||
@ -451,13 +449,15 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
|
|||||||
ncdirect_set_fg_rgb(nc, rescolor);
|
ncdirect_set_fg_rgb(nc, rescolor);
|
||||||
printf("%8s", demos[results[i].selector - 'a'].name);
|
printf("%8s", demos[results[i].selector - 'a'].name);
|
||||||
ncdirect_set_fg_rgb8(nc, 178, 102, 255);
|
ncdirect_set_fg_rgb8(nc, 178, 102, 255);
|
||||||
printf("│%*ss│%7ju│%*s│ %*ss│%7.1f│%2jd│%2jd│%*s║",
|
printf("│%*ss│%7ju│%*s│%7.1f│%2jd│%2jd│%2jd│%*s║",
|
||||||
PREFIXFMT(timebuf), (uintmax_t)(results[i].stats.renders),
|
PREFIXFMT(timebuf), (uintmax_t)(results[i].stats.renders),
|
||||||
BPREFIXFMT(totalbuf), PREFIXFMT(rtimebuf),
|
BPREFIXFMT(totalbuf),
|
||||||
results[i].timens ?
|
results[i].timens ?
|
||||||
results[i].stats.renders / ((double)results[i].timens / NANOSECS_IN_SEC) : 0.0,
|
results[i].stats.renders / ((double)results[i].timens / NANOSECS_IN_SEC) : 0.0,
|
||||||
(uintmax_t)(results[i].timens ?
|
(uintmax_t)(results[i].timens ?
|
||||||
results[i].stats.render_ns * 100 / results[i].timens : 0),
|
results[i].stats.render_ns * 100 / results[i].timens : 0),
|
||||||
|
(uintmax_t)(results[i].timens ?
|
||||||
|
results[i].stats.raster_ns * 100 / results[i].timens : 0),
|
||||||
(uintmax_t)(results[i].timens ?
|
(uintmax_t)(results[i].timens ?
|
||||||
results[i].stats.writeout_ns * 100 / results[i].timens : 0),
|
results[i].stats.writeout_ns * 100 / results[i].timens : 0),
|
||||||
PREFIXFMT(tfpsbuf));
|
PREFIXFMT(tfpsbuf));
|
||||||
@ -475,13 +475,13 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
|
|||||||
}
|
}
|
||||||
qprefix(nsdelta, NANOSECS_IN_SEC, timebuf, 0);
|
qprefix(nsdelta, NANOSECS_IN_SEC, timebuf, 0);
|
||||||
bprefix(totalbytes, 1, totalbuf, 0);
|
bprefix(totalbytes, 1, totalbuf, 0);
|
||||||
qprefix(totalrenderns, NANOSECS_IN_SEC, rtimebuf, 0);
|
//qprefix(totalrenderns, NANOSECS_IN_SEC, rtimebuf, 0);
|
||||||
table_segment(nc, "", "══╧════════╧════════╪═══════╪═════════╪═════════╪═══════╪══╧══╧═══════╝\n");
|
table_segment(nc, "", "══╧════════╧════════╪═══════╪═════════╪═══════╪══╧══╧══╧═══════╝\n");
|
||||||
printf(" ");
|
printf(" ");
|
||||||
table_printf(nc, "│", "%*ss", PREFIXFMT(timebuf));
|
table_printf(nc, "│", "%*ss", PREFIXFMT(timebuf));
|
||||||
table_printf(nc, "│", "%7lu", totalframes);
|
table_printf(nc, "│", "%7lu", totalframes);
|
||||||
table_printf(nc, "│", "%*s", BPREFIXFMT(totalbuf));
|
table_printf(nc, "│", "%*s", BPREFIXFMT(totalbuf));
|
||||||
table_printf(nc, "│", " %*ss", PREFIXFMT(rtimebuf));
|
//table_printf(nc, "│", " %*ss", PREFIXFMT(rtimebuf));
|
||||||
table_printf(nc, "│", "%7.1f", nsdelta ? totalframes / ((double)nsdelta / NANOSECS_IN_SEC) : 0);
|
table_printf(nc, "│", "%7.1f", nsdelta ? totalframes / ((double)nsdelta / NANOSECS_IN_SEC) : 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
ncdirect_set_fg_rgb8(nc, 0xff, 0xb0, 0xb0);
|
ncdirect_set_fg_rgb8(nc, 0xff, 0xb0, 0xb0);
|
||||||
|
@ -712,6 +712,7 @@ static void
|
|||||||
stash_stats(notcurses* nc){
|
stash_stats(notcurses* nc){
|
||||||
nc->stashstats.renders += nc->stats.renders;
|
nc->stashstats.renders += nc->stats.renders;
|
||||||
nc->stashstats.render_ns += nc->stats.render_ns;
|
nc->stashstats.render_ns += nc->stats.render_ns;
|
||||||
|
nc->stashstats.raster_ns += nc->stats.raster_ns;
|
||||||
nc->stashstats.writeouts += nc->stats.writeouts;
|
nc->stashstats.writeouts += nc->stats.writeouts;
|
||||||
nc->stashstats.writeout_ns += nc->stats.writeout_ns;
|
nc->stashstats.writeout_ns += nc->stats.writeout_ns;
|
||||||
nc->stashstats.failed_renders += nc->stats.failed_renders;
|
nc->stashstats.failed_renders += nc->stats.failed_renders;
|
||||||
@ -735,6 +736,12 @@ stash_stats(notcurses* nc){
|
|||||||
if(nc->stashstats.writeout_min_ns > nc->stats.writeout_min_ns){
|
if(nc->stashstats.writeout_min_ns > nc->stats.writeout_min_ns){
|
||||||
nc->stashstats.writeout_min_ns = nc->stats.writeout_min_ns;
|
nc->stashstats.writeout_min_ns = nc->stats.writeout_min_ns;
|
||||||
}
|
}
|
||||||
|
if(nc->stashstats.raster_max_ns < nc->stats.raster_max_ns){
|
||||||
|
nc->stashstats.raster_max_ns = nc->stats.raster_max_ns;
|
||||||
|
}
|
||||||
|
if(nc->stashstats.raster_min_ns > nc->stats.raster_min_ns){
|
||||||
|
nc->stashstats.raster_min_ns = nc->stats.raster_min_ns;
|
||||||
|
}
|
||||||
nc->stashstats.cellelisions += nc->stats.cellelisions;
|
nc->stashstats.cellelisions += nc->stats.cellelisions;
|
||||||
nc->stashstats.cellemissions += nc->stats.cellemissions;
|
nc->stashstats.cellemissions += nc->stats.cellemissions;
|
||||||
nc->stashstats.fgelisions += nc->stats.fgelisions;
|
nc->stashstats.fgelisions += nc->stats.fgelisions;
|
||||||
@ -1154,6 +1161,13 @@ int notcurses_stop(notcurses* nc){
|
|||||||
fprintf(stderr, "\n%ju render%s, %ss total (%ss min, %ss max, %ss avg)\n",
|
fprintf(stderr, "\n%ju render%s, %ss total (%ss min, %ss max, %ss avg)\n",
|
||||||
nc->stashstats.renders, nc->stashstats.renders == 1 ? "" : "s",
|
nc->stashstats.renders, nc->stashstats.renders == 1 ? "" : "s",
|
||||||
totalbuf, minbuf, maxbuf, avgbuf);
|
totalbuf, minbuf, maxbuf, avgbuf);
|
||||||
|
qprefix(nc->stashstats.raster_ns, NANOSECS_IN_SEC, totalbuf, 0);
|
||||||
|
qprefix(nc->stashstats.raster_min_ns, NANOSECS_IN_SEC, minbuf, 0);
|
||||||
|
qprefix(nc->stashstats.raster_max_ns, NANOSECS_IN_SEC, maxbuf, 0);
|
||||||
|
qprefix(nc->stashstats.raster_ns / nc->stashstats.writeouts, NANOSECS_IN_SEC, avgbuf, 0);
|
||||||
|
fprintf(stderr, "%ju raster%s, %ss total (%ss min, %ss max, %ss avg)\n",
|
||||||
|
nc->stashstats.writeouts, nc->stashstats.writeouts == 1 ? "" : "s",
|
||||||
|
totalbuf, minbuf, maxbuf, avgbuf);
|
||||||
qprefix(nc->stashstats.writeout_ns, NANOSECS_IN_SEC, totalbuf, 0);
|
qprefix(nc->stashstats.writeout_ns, NANOSECS_IN_SEC, totalbuf, 0);
|
||||||
qprefix(nc->stashstats.writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0);
|
qprefix(nc->stashstats.writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0);
|
||||||
qprefix(nc->stashstats.writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0);
|
qprefix(nc->stashstats.writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user