Allow per-CPU statistics to be toggled at runtime via the 'P' key.

While here, make -P a toggle similar to other options such as -I.

Reviewed by:	arundel
MFC after:	1 week
This commit is contained in:
John Baldwin 2011-07-11 16:48:52 +00:00
parent e24134bc0e
commit 51f202e9ed
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223936
5 changed files with 119 additions and 82 deletions

View File

@ -88,6 +88,7 @@ o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid)\n",
stdout);
#endif
fputs("\
P - toggle the displaying of per-CPU statistics\n\
r - renice a process\n\
s - change number of seconds to delay between updates\n\
S - toggle the displaying of system processes\n\

View File

@ -151,6 +151,26 @@ int display_resize()
return(smart_terminal ? lines : Largest);
}
int display_updatecpus(statics)
struct statics *statics;
{
register int lines;
register int i;
/* call resize to do the dirty work */
lines = display_resize();
num_cpus = statics->ncpus;
cpustates_column = 5; /* CPU: */
if (num_cpus != 1)
cpustates_column += 2; /* CPU 0: */
for (i = num_cpus; i > 9; i /= 10)
cpustates_column++;
return(lines);
}
int display_init(statics)
struct statics *statics;
@ -161,14 +181,7 @@ struct statics *statics;
register int *ip;
register int i;
/* call resize to do the dirty work */
lines = display_resize();
num_cpus = statics->ncpus;
cpustates_column = 5; /* CPU: */
if (num_cpus != 1)
cpustates_column += 2; /* CPU 0: */
for (i = num_cpus; i > 9; i /= 10)
cpustates_column++;
lines = display_updatecpus(statics);
/* only do the rest if we need to */
if (lines > -1)

View File

@ -205,6 +205,7 @@ The options
.BR \-H ,
.BR \-I ,
.BR \-j ,
.BR \-P ,
.BR \-S ,
.BR \-t ,
.BR \-u ,
@ -314,6 +315,9 @@ Toggle the display of
.IR jail (8)
ID.
.TP
.B P
Toggle the display of per-CPU statistics.
.TP
.B t
Toggle the display of the
.I top

View File

@ -196,9 +196,9 @@ char *argv[];
fd_set readfds;
#ifdef ORDER
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzo";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPo";
#else
static char command_chars[] = "\f qh?en#sdkriIutHmSCajz";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzP";
#endif
/* these defines enumerate the "strchr"s of the commands in command_chars */
#define CMD_redraw 0
@ -225,8 +225,9 @@ char *argv[];
#define CMD_showargs 20
#define CMD_jidtog 21
#define CMD_kidletog 22
#define CMD_pcputog 23
#ifdef ORDER
#define CMD_order 23
#define CMD_order 24
#endif
/* set the buffer for stdout */
@ -411,7 +412,7 @@ char *argv[];
break;
case 'P':
pcpu_stats = Yes;
pcpu_stats = !pcpu_stats;
break;
case 'z':
@ -1088,6 +1089,16 @@ char *argv[];
ps.kidle ? "D" : "Not d");
putchar('\r');
break;
case CMD_pcputog:
pcpu_stats = !pcpu_stats;
new_message(MT_standout | MT_delayed,
" Displaying %sCPU statistics.",
pcpu_stats ? "per-" : "global ");
toggle_pcpustats(&statics);
max_topn = display_updatecpus(&statics);
reset_display();
putchar('\r');
break;
default:
new_message(MT_standout, " BAD CASE IN SWITCH!");
putchar('\r');

View File

@ -239,19 +239,48 @@ static const char *format_nice(const struct kinfo_proc *pp);
static void getsysctl(const char *name, void *ptr, size_t len);
static int swapmode(int *retavail, int *retfree);
void
toggle_pcpustats(struct statics *statics)
{
if (ncpus == 1)
return;
/* Adjust display based on ncpus */
if (pcpu_stats) {
y_mem += ncpus - 1; /* 3 */
y_swap += ncpus - 1; /* 4 */
y_idlecursor += ncpus - 1; /* 5 */
y_message += ncpus - 1; /* 5 */
y_header += ncpus - 1; /* 6 */
y_procs += ncpus - 1; /* 7 */
Header_lines += ncpus - 1; /* 7 */
statics->ncpus = ncpus;
} else {
y_mem = 3;
y_swap = 4;
y_idlecursor = 5;
y_message = 5;
y_header = 6;
y_procs = 7;
Header_lines = 7;
statics->ncpus = 1;
}
}
int
machine_init(struct statics *statics, char do_unames)
{
int pagesize;
size_t modelen;
int i, j, empty, pagesize;
size_t size;
struct passwd *pw;
modelen = sizeof(smpmode);
if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen,
size = sizeof(smpmode);
if ((sysctlbyname("machdep.smp_active", &smpmode, &size,
NULL, 0) != 0 &&
sysctlbyname("kern.smp.active", &smpmode, &modelen,
sysctlbyname("kern.smp.active", &smpmode, &size,
NULL, 0) != 0) ||
modelen != sizeof(smpmode))
size != sizeof(smpmode))
smpmode = 0;
if (do_unames) {
@ -299,51 +328,37 @@ machine_init(struct statics *statics, char do_unames)
statics->order_names = ordernames;
#endif
/* Adjust display based on ncpus */
if (pcpu_stats) {
int i, j, empty;
size_t size;
cpumask = 0;
ncpus = 0;
GETSYSCTL("kern.smp.maxcpus", maxcpu);
size = sizeof(long) * maxcpu * CPUSTATES;
times = malloc(size);
if (times == NULL)
err(1, "malloc %zd bytes", size);
if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1)
err(1, "sysctlbyname kern.cp_times");
pcpu_cp_time = calloc(1, size);
maxid = (size / CPUSTATES / sizeof(long)) - 1;
for (i = 0; i <= maxid; i++) {
empty = 1;
for (j = 0; empty && j < CPUSTATES; j++) {
if (times[i * CPUSTATES + j] != 0)
empty = 0;
}
if (!empty) {
cpumask |= (1ul << i);
ncpus++;
}
/* Allocate state for per-CPU stats. */
cpumask = 0;
ncpus = 0;
GETSYSCTL("kern.smp.maxcpus", maxcpu);
size = sizeof(long) * maxcpu * CPUSTATES;
times = malloc(size);
if (times == NULL)
err(1, "malloc %zd bytes", size);
if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1)
err(1, "sysctlbyname kern.cp_times");
pcpu_cp_time = calloc(1, size);
maxid = (size / CPUSTATES / sizeof(long)) - 1;
for (i = 0; i <= maxid; i++) {
empty = 1;
for (j = 0; empty && j < CPUSTATES; j++) {
if (times[i * CPUSTATES + j] != 0)
empty = 0;
}
if (ncpus > 1) {
y_mem += ncpus - 1; /* 3 */
y_swap += ncpus - 1; /* 4 */
y_idlecursor += ncpus - 1; /* 5 */
y_message += ncpus - 1; /* 5 */
y_header += ncpus - 1; /* 6 */
y_procs += ncpus - 1; /* 7 */
Header_lines += ncpus - 1; /* 7 */
if (!empty) {
cpumask |= (1ul << i);
ncpus++;
}
size = sizeof(long) * ncpus * CPUSTATES;
pcpu_cp_old = calloc(1, size);
pcpu_cp_diff = calloc(1, size);
pcpu_cpu_states = calloc(1, size);
statics->ncpus = ncpus;
} else {
statics->ncpus = 1;
}
size = sizeof(long) * ncpus * CPUSTATES;
pcpu_cp_old = calloc(1, size);
pcpu_cp_diff = calloc(1, size);
pcpu_cpu_states = calloc(1, size);
statics->ncpus = 1;
if (pcpu_stats)
toggle_pcpustats(statics);
/* all done! */
return (0);
@ -398,14 +413,11 @@ get_system_info(struct system_info *si)
int i, j;
size_t size;
/* get the cp_time array */
if (pcpu_stats) {
size = (maxid + 1) * CPUSTATES * sizeof(long);
if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1)
err(1, "sysctlbyname kern.cp_times");
} else {
GETSYSCTL("kern.cp_time", cp_time);
}
/* get the CPU stats */
size = (maxid + 1) * CPUSTATES * sizeof(long);
if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1)
err(1, "sysctlbyname kern.cp_times");
GETSYSCTL("kern.cp_time", cp_time);
GETSYSCTL("vm.loadavg", sysload);
GETSYSCTL("kern.lastpid", lastpid);
@ -413,21 +425,17 @@ get_system_info(struct system_info *si)
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
if (pcpu_stats) {
for (i = j = 0; i <= maxid; i++) {
if ((cpumask & (1ul << i)) == 0)
continue;
/* convert cp_time counts to percentages */
percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES],
&pcpu_cp_time[j * CPUSTATES],
&pcpu_cp_old[j * CPUSTATES],
&pcpu_cp_diff[j * CPUSTATES]);
j++;
}
} else {
/* convert cp_time counts to percentages */
percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* convert cp_time counts to percentages */
for (i = j = 0; i <= maxid; i++) {
if ((cpumask & (1ul << i)) == 0)
continue;
percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES],
&pcpu_cp_time[j * CPUSTATES],
&pcpu_cp_old[j * CPUSTATES],
&pcpu_cp_diff[j * CPUSTATES]);
j++;
}
percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* sum memory & swap statistics */
{