Add a toggle to display the approximate amount of swap used by each

process.  We don't *quite* pull that number out of our backside, as
the actual number is difficult to determine without modifying the VM
system to report it, but it's still useful to get an idea of what's
going on when a machine unexpectedly starts swapping.

MFC after:	1 week
This commit is contained in:
Dag-Erling Smørgrav 2016-09-05 08:27:04 +00:00
parent 031986c4f3
commit b6924c9309
5 changed files with 95 additions and 22 deletions

View File

@ -104,6 +104,7 @@ S - toggle the displaying of system processes\n\
a - toggle the displaying of process titles\n\
t - toggle the display of this process\n\
u - display processes for only one user (+ selects all users)\n\
w - toggle the display of swap use for each process\n\
z - toggle the displaying of the system idle process\n\
\n\
\n", stdout);

View File

@ -72,6 +72,7 @@ struct process_select
int wcpu; /* show weighted cpu */
int jid; /* only this jid (unless jid == -1) */
int jail; /* show jail ID */
int swap; /* show swap usage */
int kidle; /* show per-CPU idle threads */
char *command; /* only this command (unless == NULL) */
};
@ -82,8 +83,8 @@ char *format_header();
char *format_next_process();
void toggle_pcpustats(void);
void get_system_info(struct system_info *si);
int machine_init(struct statics *statics, char do_unames);
int proc_owner(int pid);
int machine_init(struct statics *statics, char do_unames);
int proc_owner(int pid);
/* non-int routines typically used by the machine dependent module */
char *printable();

View File

@ -188,9 +188,9 @@ char *argv[];
fd_set readfds;
#ifdef ORDER
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
#else
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
#endif
/* these defines enumerate the "strchr"s of the commands in command_chars */
#define CMD_redraw 0
@ -219,8 +219,9 @@ char *argv[];
#define CMD_kidletog 22
#define CMD_pcputog 23
#define CMD_jail 24
#define CMD_swaptog 25
#ifdef ORDER
#define CMD_order 25
#define CMD_order 26
#endif
/* set the buffer for stdout */
@ -254,6 +255,7 @@ char *argv[];
ps.wcpu = 1;
ps.jid = -1;
ps.jail = No;
ps.swap = No;
ps.kidle = Yes;
ps.command = NULL;
@ -280,7 +282,7 @@ char *argv[];
optind = 1;
}
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
{
switch(i)
{
@ -418,6 +420,10 @@ char *argv[];
pcpu_stats = !pcpu_stats;
break;
case 'w':
ps.swap = 1;
break;
case 'z':
ps.kidle = !ps.kidle;
break;
@ -1141,6 +1147,15 @@ char *argv[];
reset_display();
putchar('\r');
break;
case CMD_swaptog:
ps.swap = !ps.swap;
new_message(MT_standout | MT_delayed,
" %sisplaying per-process swap usage.",
ps.swap ? "D" : "Not d");
header_text = format_header(uname_field);
reset_display();
putchar('\r');
break;
default:
new_message(MT_standout, " BAD CASE IN SWITCH!");
putchar('\r');

View File

@ -10,7 +10,7 @@ top \- display and update information about the top cpu processes
.SH SYNOPSIS
.B top
[
.B \-abCHIijnPqStuvz
.B \-abCHIijnPqStuvwz
] [
.BI \-d count
] [
@ -148,6 +148,9 @@ Write version number information to stderr then exit immediately.
No other processing takes place when this option is used. To see current
revision information while top is running, use the help command \*(lq?\*(rq.
.TP
.B \-w
Display approximate swap usage for each process.
.TP
.B \-z
Do not display the system idle process.
.TP
@ -167,11 +170,12 @@ Set the delay between screen updates to
seconds. The default delay between updates is \nD seconds.
.TP
.BI \-o field
Sort the process display area on the specified field. The field name is
the name of the column as seen in the output, but in lower case. Likely
values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq,
but may vary on different operating systems. Note that
not all operating systems support this option.
Sort the process display area on the specified field. The field name
is the name of the column as seen in the output, but in lower case:
\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
.TP
.BI \-J jail
Show only those processes owned by
@ -226,6 +230,7 @@ The options
.BR \-S ,
.BR \-t ,
.BR \-u ,
.BR \-w ,
and
.B \-z
are actually toggles. A second specification of any of these options
@ -346,6 +351,9 @@ Toggle the display of the
.I top
process.
.TP
.B w
Toggle the display of swap usage.
.TP
.B z
Toggle the display of the system idle process.
.SH "THE DISPLAY"
@ -379,8 +387,9 @@ is specified, a UID column will be substituted for USERNAME),
PRI is the current priority of the process,
NICE is the nice amount (in the range \-20 to 20),
SIZE is the total size of the process (text, data, and stack),
RES is the current amount of resident memory (both SIZE and RES are
given in kilobytes),
RES is the current amount of resident memory,
SWAP is the approximate amount of swap, if enabled
(SIZE, RES and SWAP are given in kilobytes),
STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the

View File

@ -69,7 +69,9 @@ static int namelength = 8;
#endif
/* TOP_JID_LEN based on max of 999999 */
#define TOP_JID_LEN 7
#define TOP_SWAP_LEN 6
static int jidlength;
static int swaplength;
static int cmdlengthdelta;
/* Prototypes for top internals */
@ -111,20 +113,20 @@ static char io_header[] =
"%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s"
static char smp_header_thr[] =
" PID%*s %-*.*s THR PRI NICE SIZE RES STATE C TIME %7s COMMAND";
" PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
static char smp_header[] =
" PID%*s %-*.*s " "PRI NICE SIZE RES STATE C TIME %7s COMMAND";
" PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
#define smp_Proc_format \
"%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s %2d%7s %6.2f%% %.*s"
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s"
static char up_header_thr[] =
" PID%*s %-*.*s THR PRI NICE SIZE RES STATE TIME %7s COMMAND";
" PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
static char up_header[] =
" PID%*s %-*.*s " "PRI NICE SIZE RES STATE TIME %7s COMMAND";
" PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
#define up_Proc_format \
"%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s%.0d%7s %6.2f%% %.*s"
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s"
/* process state names for the "STATE" column of the display */
@ -227,6 +229,10 @@ static int pageshift; /* log base 2 of the pagesize */
#define pagetok(size) ((size) << pageshift)
/* swap usage */
#define ki_swap(kip) \
((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0)
/* useful externals */
long percentages();
@ -237,7 +243,7 @@ long percentages();
char *ordernames[] = {
"cpu", "size", "res", "time", "pri", "threads",
"total", "read", "write", "fault", "vcsw", "ivcsw",
"jid", "pid", NULL
"jid", "swap", "pid", NULL
};
#endif
@ -252,6 +258,7 @@ static long *pcpu_cp_old;
static long *pcpu_cp_diff;
static int *pcpu_cpu_states;
static int compare_swap(const void *a, const void *b);
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
static int compare_tid(const void *a, const void *b);
@ -412,6 +419,11 @@ format_header(char *uname_field)
else
jidlength = 0;
if (ps.swap)
swaplength = TOP_SWAP_LEN + 1; /* +1 for extra left space */
else
swaplength = 0;
switch (displaymode) {
case DISP_CPU:
/*
@ -426,6 +438,7 @@ format_header(char *uname_field)
snprintf(Header, sizeof(Header), prehead,
jidlength, ps.jail ? " JID" : "",
namelength, namelength, uname_field,
swaplength, ps.swap ? " SWAP" : "",
ps.wcpu ? "WCPU" : "CPU");
break;
case DISP_IO:
@ -902,7 +915,8 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
int cpu, state;
struct rusage ru, *rup;
long p_tot, s_tot;
char *proc_fmt, thr_buf[6], jid_buf[TOP_JID_LEN + 1];
char *proc_fmt, thr_buf[6];
char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1];
char *cmdbuf = NULL;
char **args;
const int cmdlen = 128;
@ -1061,6 +1075,13 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
snprintf(jid_buf, sizeof(jid_buf), "%*d",
jidlength - 1, pp->ki_jid);
if (ps.swap == 0)
swap_buf[0] = '\0';
else
snprintf(swap_buf, sizeof(swap_buf), "%*s",
swaplength - 1,
format_k2(pagetok(ki_swap(pp)))); /* XXX */
if (displaymode == DISP_IO) {
oldp = get_old_proc(pp);
if (oldp != NULL) {
@ -1122,6 +1143,7 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
format_nice(pp),
format_k2(PROCSIZE(pp)),
format_k2(pagetok(pp->ki_rssize)),
swaplength, swaplength, swap_buf,
status,
cpu,
format_time(cputime),
@ -1309,6 +1331,12 @@ static int sorted_state[] = {
return (diff > 0 ? 1 : -1); \
} while (0)
#define ORDERKEY_SWAP(a, b) do { \
int diff = (int)ki_swap(b) - (int)ki_swap(a); \
if (diff != 0) \
return (diff > 0 ? 1 : -1); \
} while (0)
/* compare_cpu - the comparison function for sorting by cpu percentage */
int
@ -1357,6 +1385,7 @@ int (*compares[])() = {
compare_vcsw,
compare_ivcsw,
compare_jid,
compare_swap,
NULL
};
@ -1467,6 +1496,24 @@ compare_jid(const void *arg1, const void *arg2)
return (0);
}
/* compare_swap - the comparison function for sorting by swap */
static int
compare_swap(const void *arg1, const void *arg2)
{
struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
ORDERKEY_SWAP(p1, p2);
ORDERKEY_PCTCPU(p1, p2);
ORDERKEY_CPTICKS(p1, p2);
ORDERKEY_STATE(p1, p2);
ORDERKEY_PRIO(p1, p2);
ORDERKEY_RSSIZE(p1, p2);
ORDERKEY_MEM(p1, p2);
return (0);
}
#endif /* ORDER */
/* assorted comparison functions for sorting by i/o */