From 3da7318683d2fea10526384e0a4368a378b486a5 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Mon, 25 Jun 2018 00:00:00 -0500 Subject: [PATCH] top: parent total cpu includes collapsed children, pgm Now, when a parent's children have been collapsed, the cpu used by those unseen tasks will disappear no more. Instead such tics will be added to the parent's total. [ if one wished a return to the 'land of lost tics', ] [ the '#define TREE_VCPUOFF' directive is available. ] ------------------------------------------------------ Note: With collapsible parents now displaying children cpu usage, it will eventually be noticed the cpu stats for the summary area and task areas often vary widely. It's worth a reminder that for top's summary area each individual cpu and the cpu summary is limited to 100%, regardless of how many tics a linux kernel may export. An individual task is limited to 100% times the number of threads. But, in no case will cpu usage ever exceed 100% times total number of processors. Such limits are further reduced under 'Solaris' mode ('I' toggle off). In this mode, a task cpu usage will never exceed 100%. These limits will now also apply to collapsed parents. In addition to those influences, results are subjected to kernel timer sampling anomalies and the distortions inherent in a small sample size, made worse by smaller delay intervals. Often there is just 1 or 2 tics for a few tasks at smaller intervals such as: 1/10th second. Anyway, should questions on this subject arise, a good starting point, beyond the reminders above, is the 1st link listed below. Those other links were derivatives. Reference(s): . from the kernel documentation https://www.kernel.org/doc/Documentation/cpu-load.txt . as mentioned in the above kernel documentation https://lkml.org/lkml/2007/2/12/6 . from above, with many more links on the subject https://www.boblycat.org/~malc/apc/ Signed-off-by: Jim Warner top: parent total cpu includes collapsed children, pgm --- top/top.c | 24 ++++++++++++++++++++++-- top/top.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/top/top.c b/top/top.c index fb5ff49f..ca4b0b2c 100644 --- a/top/top.c +++ b/top/top.c @@ -4684,13 +4684,16 @@ static inline int wins_usrselect (const WIN_t *q, const int idx) { static proc_t **Seed_ppt; // temporary win ppt pointer static proc_t **Tree_ppt; // forest_create will resize static int Tree_idx; // frame_make resets to zero - /* those next two support collapse/expand children. the Hide_pid + /* the next three support collapse/expand children. the Hide_pid array holds parent pids whose children have been manipulated. positive pid values represent parents with collapsed children while a negative pid value means children have been expanded. ( both of these are managed under the 'keys_task()' routine ) */ static int *Hide_pid; // collapsible process array static int Hide_tot; // total used in above array +#ifndef TREE_VCPUOFF +static int *Hide_cpu; // accum tics from collapsed +#endif /* * This little recursive guy is the real forest view workhorse. @@ -4745,6 +4748,9 @@ static void forest_create (WIN_t *q) { hwmsav = Frame_maxtask; Tree_ppt = alloc_r(Tree_ppt, sizeof(proc_t*) * hwmsav); Hide_pid = alloc_r(Hide_pid, sizeof(int) * hwmsav); +#ifndef TREE_VCPUOFF + Hide_cpu = alloc_r(Hide_cpu, sizeof(int) * hwmsav); +#endif } #ifndef TREE_SCANALL @@ -4754,6 +4760,9 @@ static void forest_create (WIN_t *q) { if (!Seed_ppt[i]->pad_3) // real & pseudo parents == zero forest_adds(i, 0); // add a parent and its children } +#ifndef TREE_VCPUOFF + memset(Hide_cpu, 0, sizeof(int) * Frame_maxtask); +#endif /* we're borrowing some pad bytes in the proc_t, pad_2: 'x' means a collapsed thread, 'z' means an unseen child pad_3: where level number is stored (0 - 100) */ @@ -4767,6 +4776,9 @@ static void forest_create (WIN_t *q) { while (j+1 < Frame_maxtask && Tree_ppt[j+1]->pad_3 > level) { Tree_ppt[j+1]->pad_2 = 'z'; +#ifndef TREE_VCPUOFF + Hide_cpu[parent] += Tree_ppt[j+1]->pcpu; +#endif children = 1; ++j; } @@ -5987,10 +5999,18 @@ static const char *task_show (const WIN_t *q, const int idx) { cp = make_num(p->processor, W, Jn, AUTOX_NO, 0); break; case EU_CPU: - { float u = (float)p->pcpu * Frame_etscale; + { float u = (float)p->pcpu; +#ifndef TREE_VCPUOFF + // Hide_cpu entry is always zero, unless we're a collapsed parent + u += Hide_cpu[idx]; + u *= Frame_etscale; + if (p->pad_2 != 'x' && u > 100.0 * p->nlwp) u = 100.0 * p->nlwp; +#else + u *= Frame_etscale; /* process can't use more %cpu than number of threads it has ( thanks Jaromir Capik ) */ if (u > 100.0 * p->nlwp) u = 100.0 * p->nlwp; +#endif if (u > Cpu_pmax) u = Cpu_pmax; cp = scale_pcnt(u, W, Jn); } diff --git a/top/top.h b/top/top.h index fbbe1331..d2719eb2 100644 --- a/top/top.h +++ b/top/top.h @@ -56,6 +56,7 @@ //#define TERMIOS_ONLY /* just limp along with native input only */ //#define TREE_NORESET /* sort keys do NOT force forest view OFF */ //#define TREE_SCANALL /* rescan array w/ forest view, avoid sort */ +//#define TREE_VCPUOFF /* a collapsed parent excludes child's cpu */ //#define TREE_VPROMPT /* pid collapse/expand prompt, vs. top row */ //#define TREE_VWINALL /* pid collapse/expand impacts all windows */ //#define USE_X_COLHDR /* emphasize header vs. whole col, for 'x' */