Add a -P flag to display per-cpu cpu usage stats.

This commit is contained in:
Peter Wemm 2008-01-18 01:43:14 +00:00
parent 905925d349
commit 031175705e
6 changed files with 202 additions and 44 deletions

View file

@ -78,8 +78,10 @@ static int *lcpustates;
static int *lmemory;
static int *lswap;
static int num_cpus;
static int *cpustate_columns;
static int cpustate_total_length;
static int cpustates_column;
static enum { OFF, ON, ERASE } header_status = ON;
@ -87,6 +89,29 @@ static int string_count();
static void summary_format();
static void line_update();
int x_lastpid = 10;
int y_lastpid = 0;
int x_loadave = 33;
int x_loadave_nompid = 15;
int y_loadave = 0;
int x_procstate = 0;
int y_procstate = 1;
int x_brkdn = 15;
int y_brkdn = 1;
int x_mem = 5;
int y_mem = 3;
int x_swap = 6;
int y_swap = 4;
int y_message = 5;
int x_header = 0;
int y_header = 6;
int x_idlecursor = 0;
int y_idlecursor = 5;
int y_procs = 7;
int y_cpustates = 2;
int Header_lines = 7;
int display_resize()
{
@ -138,6 +163,12 @@ struct statics *statics;
/* 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++;
/* only do the rest if we need to */
if (lines > -1)
@ -153,7 +184,7 @@ struct statics *statics;
num_swap = string_count(swap_names);
lswap = (int *)malloc(num_swap * sizeof(int));
num_cpustates = string_count(cpustate_names);
lcpustates = (int *)malloc(num_cpustates * sizeof(int));
lcpustates = (int *)malloc(num_cpustates * sizeof(int) * num_cpus);
cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));
memory_names = statics->memory_names;
@ -365,14 +396,13 @@ int *brkdn;
}
}
#ifdef no_more
/*
* *_cpustates(states, names) - print the cpu state percentages
*
* Assumptions: cursor is on the PREVIOUS line
*/
static int cpustates_column;
/* cpustates_tag() calculates the correct tag to use to label the line */
char *cpustates_tag()
@ -398,6 +428,7 @@ char *cpustates_tag()
cpustates_column = strlen(use);
return(use);
}
#endif
i_cpustates(states)
@ -406,11 +437,18 @@ register int *states;
{
register int i = 0;
register int value;
register char **names = cpustate_names;
register char **names;
register char *thisname;
int cpu;
for (cpu = 0; cpu < num_cpus; cpu++) {
names = cpustate_names;
/* print tag and bump lastline */
printf("\n%s", cpustates_tag());
if (num_cpus == 1)
printf("\nCPU: ");
else
printf("\nCPU %d: ", cpu);
lastline++;
/* now walk thru the names and print the line */
@ -423,14 +461,15 @@ register int *states;
/* if percentage is >= 1000, print it as 100% */
printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
i++ == 0 ? "" : ", ",
(i++ % num_cpustates) == 0 ? "" : ", ",
((float)value)/10.,
thisname);
}
}
}
/* copy over values into "last" array */
memcpy(lcpustates, states, num_cpustates * sizeof(int));
memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
}
u_cpustates(states)
@ -439,14 +478,18 @@ register int *states;
{
register int value;
register char **names = cpustate_names;
register char **names;
register char *thisname;
register int *lp;
register int *colp;
int cpu;
Move_to(cpustates_column, y_cpustates);
lastline = y_cpustates;
lp = lcpustates;
for (cpu = 0; cpu < num_cpus; cpu++) {
names = cpustate_names;
Move_to(cpustates_column, y_cpustates + cpu);
lastline = y_cpustates + cpu;
lp = lcpustates + (cpu * num_cpustates);
colp = cpustate_columns;
/* we could be much more optimal about this */
@ -458,8 +501,8 @@ register int *states;
if (*lp != *states)
{
/* yes, move and change */
Move_to(cpustates_column + *colp, y_cpustates);
lastline = y_cpustates;
Move_to(cpustates_column + *colp, y_cpustates + cpu);
lastline = y_cpustates + cpu;
/* retrieve value and remember it */
value = *states;
@ -479,30 +522,39 @@ register int *states;
colp++;
}
}
}
z_cpustates()
{
register int i = 0;
register char **names = cpustate_names;
register char **names;
register char *thisname;
register int *lp;
int cpu;
for (cpu = 0; cpu < num_cpus; cpu++) {
names = cpustate_names;
/* show tag and bump lastline */
printf("\n%s", cpustates_tag());
if (num_cpus == 1)
printf("\nCPU: ");
else
printf("\nCPU %d: ", cpu);
lastline++;
while ((thisname = *names++) != NULL)
{
if (*thisname != '\0')
{
printf("%s %% %s", i++ == 0 ? "" : ", ", thisname);
printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
}
}
}
/* fill the "last" array with all -1s, to insure correct updating */
lp = lcpustates;
i = num_cpustates;
i = num_cpustates * num_cpus;
while (--i >= 0)
{
*lp++ = -1;

View file

@ -4,26 +4,28 @@
* This file defines the locations on tne screen for various parts of the
* display. These definitions are used by the routines in "display.c" for
* cursor addressing.
*
* $FreeBSD$
*/
#define x_lastpid 10
#define y_lastpid 0
#define x_loadave 33
#define x_loadave_nompid 15
#define y_loadave 0
#define x_procstate 0
#define y_procstate 1
#define x_brkdn 15
#define y_brkdn 1
#define x_mem 5
#define y_mem 3
#define x_swap 6
#define y_swap 4
#define y_message 5
#define x_header 0
#define y_header 6
#define x_idlecursor 0
#define y_idlecursor 5
#define y_procs 7
extern int x_lastpid; /* 10 */
extern int y_lastpid; /* 0 */
extern int x_loadave; /* 33 */
extern int x_loadave_nompid; /* 15 */
extern int y_loadave; /* 0 */
extern int x_procstate; /* 0 */
extern int y_procstate; /* 1 */
extern int x_brkdn; /* 15 */
extern int y_brkdn; /* 1 */
extern int x_mem; /* 5 */
extern int y_mem; /* 3 */
extern int x_swap; /* 6 */
extern int y_swap; /* 4 */
extern int y_message; /* 5 */
extern int x_header; /* 0 */
extern int y_header; /* 6 */
extern int x_idlecursor; /* 0 */
extern int y_idlecursor; /* 5 */
extern int y_procs; /* 7 */
#define y_cpustates 2
extern int y_cpustates; /* 2 */

View file

@ -20,6 +20,7 @@ struct statics
#ifdef ORDER
char **order_names;
#endif
int ncpus;
};
/*
@ -43,6 +44,8 @@ struct system_info
int *memory;
int *swap;
struct timeval boottime;
unsigned long cpumask; /* bitfield of cpu states represented */
int ncpus;
};
/* cpu_states is an array of percentages * 10. For example,

View file

@ -66,6 +66,7 @@ extern char *optarg;
extern int overstrike;
static int fmt_flags = 0;
int pcpu_stats = No;
/* signal handling routines */
sigret_t leave();
@ -282,7 +283,7 @@ char *argv[];
optind = 1;
}
while ((i = getopt(ac, av, "CSIHabijnquvs:d:U:m:o:t")) != EOF)
while ((i = getopt(ac, av, "CSIHPabijnpquvs:d:U:m:o:t")) != EOF)
{
switch(i)
{
@ -407,6 +408,14 @@ char *argv[];
ps.jail = !ps.jail;
break;
case 'P':
pcpu_stats = Yes;
break;
case 'p':
pcpu_stats = No;
break;
default:
fprintf(stderr,
"Top version %s\n"

View file

@ -11,7 +11,7 @@
#define VERSION 3
/* Number of lines of header information on the standard screen */
#define Header_lines 7
extern int Header_lines; /* 7 */
/* Maximum number of columns allowed for display */
#define MAX_COLS 128
@ -45,3 +45,5 @@ enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
#define FMT_SHOWARGS 0x00000001
extern enum displaymodes displaymode;
extern int pcpu_stats;

View file

@ -51,6 +51,7 @@
#include "machine.h"
#include "screen.h"
#include "utils.h"
#include "layout.h"
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
#define SMPUNAMELEN 13
@ -220,6 +221,17 @@ char *ordernames[] = {
};
#endif
/* Per-cpu time states */
static int maxcpu;
static int maxid;
static int ncpus;
static u_long cpumask;
static long *times;
static long *pcpu_cp_time;
static long *pcpu_cp_old;
static long *pcpu_cp_diff;
static int *pcpu_cpu_states;
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
static const char *format_nice(const struct kinfo_proc *pp);
@ -286,6 +298,56 @@ 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");
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++;
}
}
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 */
}
size = sizeof(long) * ncpus * CPUSTATES;
pcpu_cp_time = malloc(size);
pcpu_cp_old = malloc(size);
pcpu_cp_diff = malloc(size);
pcpu_cpu_states = malloc(size);
bzero(pcpu_cp_time, size);
bzero(pcpu_cp_old, size);
bzero(pcpu_cp_diff, size);
bzero(pcpu_cpu_states, size);
statics->ncpus = ncpus;
} else {
statics->ncpus = 1;
}
/* all done! */
return (0);
}
@ -327,6 +389,7 @@ static int swappgsin = -1;
static int swappgsout = -1;
extern struct timeval timeout;
void
get_system_info(struct system_info *si)
{
@ -335,10 +398,17 @@ get_system_info(struct system_info *si)
int mib[2];
struct timeval boottime;
size_t bt_size;
int i;
int i, j;
size_t size;
/* get the cp_time array */
GETSYSCTL("kern.cp_time", cp_time);
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);
}
GETSYSCTL("vm.loadavg", sysload);
GETSYSCTL("kern.lastpid", lastpid);
@ -346,8 +416,20 @@ get_system_info(struct system_info *si)
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
/* convert cp_time counts to percentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
if (pcpu_stats) {
for (i = j = 0; i <= maxid; i++, j++) {
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]);
}
} else {
/* convert cp_time counts to percentages */
percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
}
/* sum memory & swap statistics */
{
@ -401,7 +483,15 @@ get_system_info(struct system_info *si)
}
/* set arrays and strings */
si->cpustates = cpu_states;
if (pcpu_stats) {
si->cpustates = pcpu_cpu_states;
si->cpumask = cpumask;
si->ncpus = ncpus;
} else {
si->cpustates = cpu_states;
si->cpumask = 1;
si->ncpus = 1;
}
si->memory = memory_stats;
si->swap = swap_stats;