diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2025-02-08 00:21:54 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2025-04-28 00:14:23 -0700 |
commit | e6a0db25a8a4176b2b7938e8899a2232eb982f36 (patch) | |
tree | 4b23989e0f197d1e18eda7499580baa6fbb08aaa | |
parent | 8aecd73cbe0471eafef90a5deea73f9e61c9d480 (diff) |
charts: first stab WIP of RSS per-process rows
-rw-r--r-- | src/charts.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/charts.c b/src/charts.c index da74400..16f8dc7 100644 --- a/src/charts.c +++ b/src/charts.c @@ -156,6 +156,9 @@ typedef struct _vwm_perproc_ctxt_t { typeof(((vmon_proc_stat_t *)0)->stime) last_stime; typeof(((vmon_proc_stat_t *)0)->utime) utime_delta; typeof(((vmon_proc_stat_t *)0)->stime) stime_delta; + typeof(((vmon_proc_stat_t *)0)->rss) prev_rss; + typeof(((vmon_proc_stat_t *)0)->rss) rss; + int rss_log2_delta; int row; } vwm_perproc_ctxt_t; @@ -371,6 +374,7 @@ static int count_rows(vmon_proc_t *proc, unsigned no_threads) vmon_proc_t *child; if (!proc->is_thread) { + count++; // add the mem row list_for_each_entry(child, &proc->threads, threads) count += count_rows(child, no_threads); } @@ -910,6 +914,24 @@ static void draw_overlay_row(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc } +static unsigned ilog2_ish(unsigned long long i) +{ + unsigned n = 0; + + /* TODO: this could use inline assembly to access arch-specific instructions for doing this in one cycle */ + while (i >>= 1) + n++; + + /* I don't want to get a zero for 1 page though, so detect that case and force it to 1, + * the RSS graph needs to show a pixel even for single page changes. + */ + if (!n && i) + n++; + + return n; +} + + /* recursive draw function for "rest" of chart: the per-process rows (hierarchy, argv, state, wchan, pid...) */ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_t *proc, int *depth, int *row, int deferred_pass, unsigned sample_duration_idx) { @@ -990,6 +1012,16 @@ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_ ((vmon_proc_stat_t *)proc->stores[VMON_STORE_PROC_STAT])->comm.array, (*depth), (*row), proc->is_thread); + /* mem row for non-threads */ + if (!proc->is_thread) { + mark_finish(charts, chart, (*row)); + /* extract the row from the various layers */ + snowflake_row(charts, chart, (*row)); + chart->snowflakes_cnt++; + chart->hierarchy_end--; + (*row)--; + } + mark_finish(charts, chart, (*row)); /* extract the row from the various layers */ @@ -1023,6 +1055,15 @@ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_ proc_ctxt->last_utime = proc_stat->utime; proc_ctxt->last_stime = proc_stat->stime; + /* TODO: this should probably be skipped if proc->is_thread? */ + proc_ctxt->prev_rss = proc_ctxt->rss; + proc_ctxt->rss = proc_stat->rss; + if (proc_ctxt->rss > proc_ctxt->prev_rss) { + proc_ctxt->rss_log2_delta = ilog2_ish(proc_ctxt->rss - proc_ctxt->prev_rss); + } else { + proc_ctxt->rss_log2_delta = -(int)ilog2_ish(proc_ctxt->prev_rss - proc_ctxt->rss); + } + proc_ctxt->generation = charts->vmon.generation; } } @@ -1059,6 +1100,11 @@ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_ chart->hierarchy_end++; + if (!proc->is_thread) { /* per-proc RSS row */ + allocate_row(charts, chart, (*row) + 1); + chart->hierarchy_end++; + } + /* we need a minimum of two samples before we can compute a delta to plot, * so we suppress that and instead mark the start of monitoring with an impossible 100% of both graph contexts, a starting line. */ stime_delta = utime_delta = charts->total_delta; @@ -1075,6 +1121,20 @@ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_ utime_delta, charts->inv_total_delta, VCR_LAYER_GRAPHB); + + if (!proc->is_thread) { + if (proc_ctxt->rss != proc_ctxt->prev_rss) { + // fprintf(stderr, "row=%i rss_delta=%i rss=%llu\n", (*row) + 1, proc_ctxt->rss_log2_delta, proc_ctxt->rss); + draw_bars(charts, chart, *row + 1, + 1.f /* mult */, + proc_ctxt->rss_log2_delta < 0.f ? proc_ctxt->rss_log2_delta : 0.f, + 1.f / (VCR_ROW_HEIGHT - 1), + VCR_LAYER_GRAPHB, + proc_ctxt->rss_log2_delta > 0.f ? proc_ctxt->rss_log2_delta : 0.f, + 1.f / (VCR_ROW_HEIGHT - 1), + VCR_LAYER_GRAPHA); + } + } } /* unless a deferred pass, only try draw the overlay on the last draw within a duration */ @@ -1083,6 +1143,8 @@ static void draw_chart_rest(vwm_charts_t *charts, vwm_chart_t *chart, vmon_proc_ /* note these are suppressed for --no-threads */ (*row)++; + if (!proc->is_thread) + (*row)++; /* per-proc RSS row */ (*depth)++; } |