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:
parent
c69104b2b8
commit
7647e96b0a
51
top/top.c
51
top/top.c
@ -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
|
||||
|
@ -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[] = { ... } */
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user