top: added fields for 'start time' & 'cpu utilization'

This patch will exploit some new library capabilities.

[ one will raise eyebrows, the other likely will not ]

A new 'STARTED' field was added which shows the time a
process started after system boot. As such the largest
interval represents the most recently started process.

This is the field that will likely be questioned since
it's somewhat counterintuitive. But were we to instead
use TIME_ELAPSED, the value will change with every top
refresh. This will defeat any PUFF macro optimization.

The new '%CUU' field will probably be better received.
It represents the cpu usage over the life of the task.
When a process was showing high %CPU usage, this field
can be used to determine if it's an anomaly or normal.

[ and as with %CPU, %CUU shows a '?' when running in ]
[ a namespace when /proc was mounted with subset=pid ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-02-25 00:00:00 -06:00 committed by Craig Small
parent c69104b2b8
commit 7647e96b0a
3 changed files with 44 additions and 16 deletions

View File

@ -1597,18 +1597,27 @@ end_justifies:
/*
* Make and then justify a percentage, with decreasing precision. */
static const char *scale_pcnt (float num, int width, int justr) {
static const char *scale_pcnt (float num, int width, int justr, int xtra) {
static char buf[SMLBUFSIZ];
buf[0] = '\0';
if (Rc.zero_suppress && 0 >= num)
goto end_justifies;
if (xtra) {
if (width >= snprintf(buf, sizeof(buf), "%#.3f", num))
goto end_justifies;
if (width >= snprintf(buf, sizeof(buf), "%#.2f", num))
goto end_justifies;
goto carry_on;
}
#ifdef BOOST_PERCNT
if (width >= snprintf(buf, sizeof(buf), "%#.3f", num))
goto end_justifies;
if (width >= snprintf(buf, sizeof(buf), "%#.2f", num))
goto end_justifies;
(void)xtra;
#endif
carry_on:
if (width >= snprintf(buf, sizeof(buf), "%#.1f", num))
goto end_justifies;
if (width >= snprintf(buf, sizeof(buf), "%*.0f", width, num))
@ -1766,23 +1775,23 @@ static struct {
{ 6, -1, A_right, PIDS_IO_WRITE_BYTES }, // ul_int EU_IWB
{ 5, -1, A_right, PIDS_IO_WRITE_OPS }, // ul_int EU_IWO
{ 5, -1, A_right, PIDS_AUTOGRP_ID }, // s_int EU_AGI
{ 4, -1, A_right, PIDS_AUTOGRP_NICE } // s_int EU_AGN
#define eu_LAST EU_AGN
{ 4, -1, A_right, PIDS_AUTOGRP_NICE }, // s_int EU_AGN
{ 9, -1, A_right, PIDS_TICS_BEGAN }, // ull_int EU_TM3
{ 6, -1, A_right, PIDS_UTILIZATION } // real EU_CUU
#define eu_LAST EU_CUU
// xtra Fieldstab 'pseudo pflag' entries for the newlib interface . . . . . . .
#define eu_CMDLINE eu_LAST +1
#define eu_TICS_ALL_C eu_LAST +2
#define eu_TIME_START eu_LAST +3
#define eu_ID_FUID eu_LAST +4
#define eu_TREE_HID eu_LAST +5
#define eu_TREE_LVL eu_LAST +6
#define eu_TREE_ADD eu_LAST +7
#define eu_ID_FUID eu_LAST +3
#define eu_TREE_HID eu_LAST +4
#define eu_TREE_LVL eu_LAST +5
#define eu_TREE_ADD eu_LAST +6
, { -1, -1, -1, PIDS_CMDLINE } // str ( if Show_CMDLIN, eu_CMDLINE )
, { -1, -1, -1, PIDS_TICS_ALL_C } // ull_int ( if Show_CTIMES, eu_TICS_ALL_C )
, { -1, -1, -1, PIDS_TIME_START } // ull_int ( if Show_FOREST, eu_TIME_START )
, { -1, -1, -1, PIDS_ID_FUID } // u_int ( if a usrseltyp, eu_ID_FUID )
, { -1, -1, -1, PIDS_extra } // s_ch ( if Show_FOREST, eu_TREE_HID )
, { -1, -1, -1, PIDS_extra } // s_int ( if Show_FOREST, eu_TREE_LVL )
, { -1, -1, -1, PIDS_extra } // u_int ( if Show_FOREST, eu_TREE_ADD )
, { -1, -1, -1, PIDS_extra } // s_int ( if Show_FOREST, eu_TREE_ADD )
#undef A_left
#undef A_right
};
@ -1956,9 +1965,9 @@ static void build_headers (void) {
if (!CHKw(w, Show_IDLEPS)) ckITEM(EU_CPU);
// with forest view mode, we'll need pid, tgid, ppid & start_time...
#ifndef TREE_VCPUOFF
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(eu_TIME_START); ckITEM(eu_TREE_HID); ckITEM(eu_TREE_LVL); ckITEM(eu_TREE_ADD); }
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(EU_TM3); ckITEM(eu_TREE_HID); ckITEM(eu_TREE_LVL); ckITEM(eu_TREE_ADD); }
#else
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(eu_TIME_START); ckITEM(eu_TREE_HID); ckITEM(eu_TREE_LVL); }
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(EU_TM3); ckITEM(eu_TREE_HID); ckITEM(eu_TREE_LVL); }
#endif
// for 'u/U' filtering we need these too (old top forgot that, oops)
if (w->usrseltyp) { ckITEM(EU_UED); ckITEM(EU_URD); ckITEM(EU_USD); ckITEM(eu_ID_FUID); }
@ -4549,7 +4558,7 @@ static void forest_begin (WIN_t *q) {
#ifndef TREE_SCANALL
if (!(procps_pids_sort(Pids_ctx, Seed_ppt, PIDSmaxt
, PIDS_TIME_START, PIDS_SORT_ASCEND)))
, PIDS_TICS_BEGAN, PIDS_SORT_ASCEND)))
error_exit(fmtmk(N_fmt(LIB_errorpid_fmt), __LINE__, strerror(errno)));
#endif
for (i = 0; i < PIDSmaxt; i++) { // avoid hidepid distorts |
@ -6158,9 +6167,17 @@ static const char *task_show (const WIN_t *q, int idx) {
if (u > 100.0 * n) u = 100.0 * n;
#endif
if (u > Cpu_pmax) u = Cpu_pmax;
cp = scale_pcnt(u, W, Jn);
cp = scale_pcnt(u, W, Jn, 0);
}
break;
/* ull_int, scale_pcnt for 'utilization' */
case EU_CUU: // PIDS_UTILIZATION
if (Restrict_some) {
cp = justify_pad("?", W, Jn);
break;
}
cp = scale_pcnt(rSv(EU_CUU, real), W, Jn, 1);
break;
/* u_int, make_num with auto width */
case EU_GID: // PIDS_ID_EGID
case EU_UED: // PIDS_ID_EUID
@ -6213,7 +6230,7 @@ static const char *task_show (const WIN_t *q, int idx) {
cp = justify_pad("?", W, Jn);
break;
}
cp = scale_pcnt((float)rSv(EU_MEM, ul_int) * 100 / MEM_VAL(mem_TOT), W, Jn);
cp = scale_pcnt((float)rSv(EU_MEM, ul_int) * 100 / MEM_VAL(mem_TOT), W, Jn, 0);
break;
/* ul_int, make_str with special handling */
case EU_FLG: // PIDS_FLAGS
@ -6228,6 +6245,10 @@ static const char *task_show (const WIN_t *q, int idx) {
cp = scale_tics(t, W, Jn);
}
break;
/* ull_int, scale_time */
case EU_TM3: // PIDS_TICS_BEGAN
cp = scale_tics(rSv(EU_TM3, ull_int), W, Jn);
break;
/* str, make_str (all AUTOX yes) */
case EU_LXC: // PIDS_LXCNAME
case EU_TTY: // PIDS_TTY_NAME

View File

@ -202,6 +202,7 @@ enum pflag {
EU_RSS, EU_PSS, EU_PZA, EU_PZF, EU_PZS, EU_USS,
EU_IRB, EU_IRO, EU_IWB, EU_IWO,
EU_AGI, EU_AGN,
EU_TM3, EU_CUU,
#ifdef USE_X_COLHDR
// not really pflags, used with tbl indexing
EU_MAXPFLGS
@ -622,7 +623,7 @@ typedef struct WIN_t {
//atic inline const char *make_str_utf8 (const char *str, int width, int justr, int col);
//atic const char *scale_mem (int target, float num, int width, int justr);
//atic const char *scale_num (float num, int width, int justr);
//atic const char *scale_pcnt (float num, int width, int justr);
//atic const char *scale_pcnt (float num, int width, int justr, int xtra);
//atic const char *scale_tics (TIC_t tics, int width, int justr);
/*------ Fields Management support -------------------------------------*/
/*atic struct Fieldstab[] = { ... } */

View File

@ -350,6 +350,12 @@ static void build_two_nlstabs (void) {
/* Translation Hint: maximum 'AGNI' = 4 */
Head_nlstab[EU_AGN] = _("AGNI");
Desc_nlstab[EU_AGN] = _("Autogroup Nice Value");
/* Translation Hint: maximum 'STARTED' = 9 */
Head_nlstab[EU_TM3] = _("STARTED");
Desc_nlstab[EU_TM3] = _("Start Time from boot");
/* Translation Hint: maximum '%CUU' = 6 */
Head_nlstab[EU_CUU] = _("%CUU");
Desc_nlstab[EU_CUU] = _("CPU Utilization");
}