NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/36542 (better "systat vm" output)
The following reply was made to PR bin/36542; it has been noted by GNATS.
From: "Greg A. Woods" <woods%planix.com@localhost>
To: NetBSD GNATS <gnats-bugs%NetBSD.org@localhost>
Cc:
Subject: Re: bin/36542 (better "systat vm" output)
Date: Mon, 10 Dec 2018 21:21:22 -0800
--pgp-sign-Multipart_Mon_Dec_10_21:21:06_2018-1
Content-Type: text/plain; charset=US-ASCII
At Tue, 11 Dec 2018 04:05:00 +0000 (UTC), Sevan Janiyan <sevan%NetBSD.org@localhost> wrote:
Subject: Re: bin/36542 (better "systat vm" output)
>
> The following reply was made to PR bin/36542; it has been noted by GNATS.
>
> I've updated your proposed patch so that it merges with the current
> version of source and posted a copy here
> http://www.netbsd.org/~sevan/patch-pr36542-mk2.txt
Thanks!
Unfortunately I won't have time to look at your patch for a few days,
but here's a quick reply containing the patch I've been using against a
much more recent source tree (I've not built this exact merge, but no
conflicts were raised and I've been running the previous build without
problems for about a year now):
Index: usr.bin/systat/bufcache.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/bufcache.c,v
retrieving revision 1.28
diff -u -r1.28 bufcache.c
--- usr.bin/systat/bufcache.c 9 Jun 2017 00:13:29 -0000 1.28
+++ usr.bin/systat/bufcache.c 9 Dec 2018 03:23:40 -0000
@@ -117,8 +117,8 @@
wmove(wnd, i, 0);
wclrtoeol(wnd);
}
- mvwaddstr(wnd, PAGEINFO_ROWS + 1, 0, "File System Bufs used"
- " % kB in use % Bufsize kB % Util %");
+ mvwaddstr(wnd, PAGEINFO_ROWS + 1, 0,
+"File System Bufs used % kB in use % Bufsize kB % Util %");
wclrtoeol(wnd);
}
Index: usr.bin/systat/cmdtab.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/cmdtab.c,v
retrieving revision 1.25
diff -u -r1.25 cmdtab.c
--- usr.bin/systat/cmdtab.c 2 Aug 2016 15:56:09 -0000 1.25
+++ usr.bin/systat/cmdtab.c 9 Dec 2018 03:23:40 -0000
@@ -52,6 +52,7 @@
{ "quit", global_quit, "exit systat"},
{ "start", global_interval, "restart updating display"},
{ "stop", global_stop, "stop updating display"},
+ { "?", global_help, "show help"},
{ .c_name = NULL }
};
@@ -114,7 +115,7 @@
{ "names", netstat_names, "show names instead of addresses"},
{ "numbers", netstat_numbers, "show addresses instead of names"},
{ "reset", netstat_reset, "return to default display"},
- { "show", netstat_show, "show current display/ignore settings"},
+ { "show", netstat_show, "show current display/ignore settings"},
{ "tcp", netstat_tcp, "show only tcp connections"},
{ "udp", netstat_udp, "show only udp connections"},
{ .c_name = NULL }
Index: usr.bin/systat/main.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/main.c,v
retrieving revision 1.53
diff -u -r1.53 main.c
--- usr.bin/systat/main.c 22 Nov 2017 02:52:42 -0000 1.53
+++ usr.bin/systat/main.c 11 Dec 2018 05:15:53 -0000
@@ -66,7 +66,7 @@
sig_t sigtstpdfl;
double avenrun[3];
int col;
-double naptime = 5;
+double naptime = 1;
int verbose = 1; /* to report kvm read errs */
int hz, stathz, maxslp;
char c;
@@ -173,10 +173,8 @@
(void)setegid(egid);
kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
- if (kd == NULL) {
- error("%s", errbuf);
- exit(1);
- }
+ if (kd == NULL)
+ errx(1, "%s", errbuf);
/* Get rid of privs for now. */
if (nlistf == NULL && memf == NULL)
@@ -194,19 +192,24 @@
* routines to minimize update work by curses.
*/
if (initscr() == NULL)
- {
- warnx("couldn't initialize screen");
- exit(0);
- }
+ errx(1, "couldn't initialize screen");
CMDLINE = LINES - 1;
wnd = (*curmode->c_open)();
if (wnd == NULL) {
+ move(CMDLINE, 0);
+ clrtoeol();
+ refresh();
+ endwin();
warnx("couldn't initialize display");
die(0);
}
wload = newwin(1, 0, 3, 20);
if (wload == NULL) {
+ move(CMDLINE, 0);
+ clrtoeol();
+ refresh();
+ endwin();
warnx("couldn't set up load average window");
die(0);
}
@@ -411,7 +414,6 @@
move(CMDLINE, 0);
clrtoeol();
refresh();
- sleep(5);
endwin();
exit(1);
}
Index: usr.bin/systat/systat.1
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/systat.1,v
retrieving revision 1.48
diff -u -r1.48 systat.1
--- usr.bin/systat/systat.1 3 Jul 2017 21:34:21 -0000 1.48
+++ usr.bin/systat/systat.1 9 Dec 2018 03:23:41 -0000
@@ -454,7 +454,22 @@
The upper left quadrant of the screen shows the number
of users logged in and the load average over the last one, five,
and fifteen minute intervals.
-Below this is a list of the
+Below this are statistics on memory utilization.
+The first row of the table reports memory usage only among
+active processes, that is processes that have run in the previous
+twenty seconds.
+The second row reports on memory usage of all processes.
+The first column reports on the number of physical pages
+claimed by processes.
+The second column reports the number of physical pages that
+are devoted to read only text pages.
+The third and fourth columns report the same two figures for
+virtual pages, that is the number of pages that would be
+needed if all processes had all of their pages.
+Finally the last column shows the number of physical pages
+on the free list.
+.Pp
+Below the memory display is a list of the
average number of processes (over the last refresh interval)
that are runnable (`r'), in page wait (`p'),
in disk wait other than paging (`d'), sleeping (`s').
@@ -465,9 +480,9 @@
.Pp
To the right of the process statistics is a column that
lists the average number of context switches (`Csw'),
-traps (`Trp'; includes page faults), system calls (`Sys'), interrupts (`Int'),
-network software interrupts (`Sof'),
-page faults (`Flt').
+traps (`Traps'; includes page faults), system calls (`SysCa'), interrupts (`Intr'),
+network software interrupts (`Soft'),
+page faults (`Fault').
.Pp
Below this are statistics on memory utilization.
The first row of the table reports memory usage only among
@@ -509,16 +524,75 @@
number of pages transferred per second over the last refresh interval.
.Pp
Below the paging statistics is another columns of paging data.
-From top to bottom, these represent average numbers of copy on write faults
-(`cow'), object cache lookups (`objlk'), object cache hits (`objht'),
-pages zero filled on demand (`zfodw'), number zfod's created (`nzfod'),
-percentage of zfod's used (`%zfod'), number of kernel pages (`kern'),
-number of wired pages (`wire'), number of active pages (`act'), number
-of inactive pages (`inact'), number of free pages (`free'), pages freed
-by daemon (`daefr'), pages freed by exiting processes (`prcfr'), number
-of pages reactivated from freelist (`react'), scans in page out daemon
-(`scan'), revolutions of the hand (`hdrev'), and in-transit blocking page
-faults (`intrn'), per second over the refresh period.
+From top to bottom, these represent:
+.Pp
+.Bl -tag -width Fl -compact
+.It Ic Sq forks
+number of fork() calls
+.It Ic Sq fkppw
+number of fork() calls where parent waits
+.It Ic Sq fksvm
+number of fork() calls where vmspace is shared
+.It Ic Sq pwait
+number of times fault had to wait on a page
+.It Ic Sq relck
+number of times uvmfault_relock() is called
+.It Ic Sq rlkok
+number of times uvmfault_relock() is a success
+.It Ic Sq noram
+number of times fault was out of RAM
+.It Ic Sq ndcpy
+number of times fault clears ``needs copy''
+.It Ic Sq fltcp
+number of times fault promotes with copy (2b)
+.It Ic Sq zfod
+number of times fault promotes with zerofill (2b)
+.It Ic Sq cow
+number of times faulted for anonymous for Copy-On-Write (case 1b)
+.It Ic Sq fmin
+min number of free pages
+.It Ic Sq ftarg
+target number of free pages
+.It Ic Sq itarg
+target number of inactive pages
+.\".It Ic Sq objlk
+.\"object cache lookups
+.\".It Ic Sq objht
+.\"object cache hits
+.\".It Ic Sq zfodw
+.\"pages zero filled on demand
+.\".It Ic Sq nzfod
+.\"number of zfod's created
+.\".It Ic Sq %zfod
+.\"percentage of zfod's used
+.\".It Ic Sq kern
+.\"number of kernel pages
+.It Ic Sq flnan
+number of times fault was out of anonymous pages
+.\".It Ic Sq act
+.\"number of active pages
+.\".It Ic Sq inact
+.\"number of inactive pages
+.\".It Ic Sq free
+.\"number of free pages
+.\".It Ic Sq daefr
+.\"pages freed by daemon
+.\".It Ic Sq prcfr
+.\"pages freed by exiting processes
+.\".It Ic Sq react
+.\"number of pages reactivated from freelist
+.\".It Ic Sq scan
+.\"scans in page out daemon
+.\".It Ic Sq hdrev
+.\"revolutions of the hand
+.\".It Ic Sq intrn
+.\"in-transit blocking page faults per second over the refresh period.
+.It Ic Sq pdfre
+number of pages daemon freed since boot
+.It Ic Sq pdscn
+number of pages daemon scaned since boot
+.El
+.Pp
Note that the `%zfod' percentage is usually less than 100%,
however it may exceed 100% if a large number of requests
are actually used long after they were set up during a
Index: usr.bin/systat/systat.h
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/systat.h,v
retrieving revision 1.11
diff -u -r1.11 systat.h
--- usr.bin/systat/systat.h 26 Feb 2005 22:12:34 -0000 1.11
+++ usr.bin/systat/systat.h 11 Feb 2007 22:29:35 -0000
@@ -61,4 +61,3 @@
#define NVAL(indx) namelist[(indx)].n_value
#define NPTR(indx) (void *)NVAL((indx))
#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len), # indx)
-#define LONG (sizeof (long))
Index: usr.bin/systat/vmstat.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/usr.bin/systat/vmstat.c,v
retrieving revision 1.82
diff -u -r1.82 vmstat.c
--- usr.bin/systat/vmstat.c 15 Jul 2017 08:22:23 -0000 1.82
+++ usr.bin/systat/vmstat.c 9 Dec 2018 03:23:41 -0000
@@ -87,6 +87,7 @@
static char **intrname;
static int nextintsrow;
static int disk_horiz = 1;
+static u_int nbuf;
WINDOW *
openvmstat(void)
@@ -124,7 +125,7 @@
*/
#define STATROW 0 /* uses 1 row and 68 cols */
#define STATCOL 2
-#define MEMROW 9 /* uses 4 rows and 31 cols */
+#define MEMROW 9 /* uses 5 rows and 31 cols */
#define MEMCOL 0
#define PAGEROW 2 /* uses 4 rows and 26 cols */
#define PAGECOL 54
@@ -139,11 +140,11 @@
#define VMSTATCOL 64
#define GRAPHROW 5 /* uses 3 rows and 51 cols */
#define GRAPHCOL 0
-#define NAMEIROW 14 /* uses 3 rows and 38 cols */
+#define NAMEIROW 15 /* uses 3 rows and 38 cols (must be MEMROW + 5 + 1) */
#define NAMEICOL 0
-#define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */
+#define DISKROW 19 /* uses 5 rows and 50 cols (for 9 drives) */
#define DISKCOL 0
-#define DISKCOLWIDTH 6
+#define DISKCOLWIDTH 8
#define DISKCOLEND INTSCOL
typedef struct intr_evcnt intr_evcnt_t;
@@ -318,7 +319,7 @@
mvprintw(STATROW, STATCOL + 4, "users Load");
- mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
+ mvprintw(GENSTATROW, GENSTATCOL, " Csw Traps SysCal Intr Soft Fault");
mvprintw(GRAPHROW, GRAPHCOL,
" . %% Sy . %% Us . %% Ni . %% In . %% Id");
@@ -328,8 +329,8 @@
mvprintw(PAGEROW, PAGECOL + 8, "PAGING SWAPPING ");
mvprintw(PAGEROW + 1, PAGECOL, " in out in out ");
- mvprintw(PAGEROW + 2, PAGECOL + 2, "ops");
- mvprintw(PAGEROW + 3, PAGECOL, "pages");
+ mvprintw(PAGEROW + 2, PAGECOL, " ops ");
+ mvprintw(PAGEROW + 3, PAGECOL, "pages ");
}
void
@@ -343,26 +344,28 @@
/* Left hand column */
- mvprintw(MEMROW, MEMCOL, " memory totals (in kB)");
- mvprintw(MEMROW + 1, MEMCOL, " real virtual free");
- mvprintw(MEMROW + 2, MEMCOL, "Active");
- mvprintw(MEMROW + 3, MEMCOL, "All");
+ mvprintw(MEMROW + 0, MEMCOL, "Anon %% zero ");
+ mvprintw(MEMROW + 1, MEMCOL, "Exec %% wired ");
+ mvprintw(MEMROW + 2, MEMCOL, "File %% inact ");
+ mvprintw(MEMROW + 3, MEMCOL, "Meta %% bufs ");
+ mvprintw(MEMROW + 4, MEMCOL, " (kB) real swaponly free");
+ mvprintw(MEMROW + 5, MEMCOL, "Active ");
mvprintw(NAMEIROW, NAMEICOL, "Namei Sys-cache Proc-cache");
mvprintw(NAMEIROW + 1, NAMEICOL,
" Calls hits %% hits %%");
- mvprintw(DISKROW, DISKCOL, "Disks:");
+ mvprintw(DISKROW, DISKCOL, "%*s", DISKCOLWIDTH, "Disks:");
if (disk_horiz) {
mvprintw(DISKROW + 1, DISKCOL + 1, "seeks");
mvprintw(DISKROW + 2, DISKCOL + 1, "xfers");
mvprintw(DISKROW + 3, DISKCOL + 1, "bytes");
mvprintw(DISKROW + 4, DISKCOL + 1, "%%busy");
} else {
- mvprintw(DISKROW, DISKCOL + 1 + 1 * DISKCOLWIDTH, "seeks");
- mvprintw(DISKROW, DISKCOL + 1 + 2 * DISKCOLWIDTH, "xfers");
- mvprintw(DISKROW, DISKCOL + 1 + 3 * DISKCOLWIDTH, "bytes");
- mvprintw(DISKROW, DISKCOL + 1 + 4 * DISKCOLWIDTH, "%%busy");
+ mvprintw(DISKROW, DISKCOL + 1 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "seeks");
+ mvprintw(DISKROW, DISKCOL + 2 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "xfers");
+ mvprintw(DISKROW, DISKCOL + 3 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "bytes");
+ mvprintw(DISKROW, DISKCOL + 4 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "%%busy");
}
/* Middle column */
@@ -396,7 +399,7 @@
mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin");
mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg");
mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg");
- mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired");
+ mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "flnan");
mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre");
if (LINES - 1 > VMSTATROW + 16)
@@ -447,6 +450,11 @@
PUTRATE(us, us1, uvmexp->softs, GENSTATROW + 1, GENSTATCOL + 27, 6);
PUTRATE(us, us1, uvmexp->faults, GENSTATROW + 1, GENSTATCOL + 34, 6);
+ /*
+ * XXX it sure would be nice if this did what top(1) does and showed
+ * the utilization of each CPU on a separate line, though perhaps IFF
+ * the screen is tall enough
+ */
/* Last CPU state not calculated yet. */
for (f2 = 0.0, psiz = 0, c = 0; c < CPUSTATES; c++) {
i = cpuorder[c];
@@ -476,6 +484,11 @@
static int relabel = 0;
static int last_disks = 0;
static char pigs[] = "pigs";
+ static u_long bufmem;
+ struct buf_sysctl *buffers;
+ int mib[6];
+ size_t size;
+ int extraslop = 0;
if (relabel) {
labelvmstat();
@@ -507,16 +520,74 @@
/* Memory totals */
#define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024))
- putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 6, 9);
- putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */
- MEMROW + 2, MEMCOL + 16, 9);
- putint(pgtokb(s.uvmexp.npages - s.uvmexp.free),
- MEMROW + 3, MEMCOL + 6, 9);
- putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse),
- MEMROW + 3, MEMCOL + 16, 9);
- putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 26, 9);
- putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse),
- MEMROW + 3, MEMCOL + 26, 9);
+
+ putint(pgtokb(s.uvmexp.anonpages), MEMROW + 0, MEMCOL + 7, 10);
+ putint((s.uvmexp.anonpages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 0, MEMCOL + 17, 4);
+
+ putint(pgtokb(s.uvmexp.zeropages), MEMROW + 0, MEMCOL + 30, 8);
+
+ putint(pgtokb(s.uvmexp.execpages), MEMROW + 1, MEMCOL + 7, 10);
+ putint((s.uvmexp.execpages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 1, MEMCOL + 17, 4);
+
+ putint(pgtokb(s.uvmexp.wired), MEMROW + 1, MEMCOL + 30, 8);
+
+ putint(pgtokb(s.uvmexp.filepages), MEMROW + 2, MEMCOL + 7, 10);
+ putint((s.uvmexp.filepages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 2, MEMCOL + 17, 4);
+
+ putint(pgtokb(s.uvmexp.inactive), MEMROW + 2, MEMCOL + 30, 8);
+
+ /* Get total size of metadata buffers */
+ size = sizeof(bufmem);
+ if (sysctlbyname("vm.bufmem", &bufmem, &size, NULL, 0) < 0) {
+ error("can't get buffers size: %s\n", strerror(errno));
+ return;
+ }
+
+ /* Get number of metadata buffers */
+ size = 0;
+ buffers = NULL;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BUF;
+ mib[2] = KERN_BUF_ALL;
+ mib[3] = KERN_BUF_ALL;
+ mib[4] = (int)sizeof(struct buf_sysctl);
+ mib[5] = INT_MAX; /* we want them all */
+again:
+ if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
+ error("can't get buffers size: %s\n", strerror(errno));
+ return;
+ }
+ if (size == 0) {
+ error("buffers size is zero: %s\n", strerror(errno));
+ return;
+ }
+ size += extraslop * sizeof(struct buf_sysctl);
+ buffers = malloc(size);
+ if (buffers == NULL) {
+ error("can't allocate buffers: %s\n", strerror(errno));
+ return;
+ }
+ if (sysctl(mib, 6, buffers, &size, NULL, 0) < 0) {
+ free(buffers);
+ if (extraslop == 0) {
+ extraslop = 100;
+ goto again;
+ }
+ error("can't get buffers: %s\n", strerror(errno));
+ return;
+ }
+ free(buffers); /* XXX there must be a better way! */
+ nbuf = size / sizeof(struct buf_sysctl);
+
+ putint((int) (bufmem / 1024), MEMROW + 3, MEMCOL + 5, 12);
+ putint((int) ((bufmem * 100) + 0.5) / s.uvmexp.pagesize / s.uvmexp.npages,
+ MEMROW + 3, MEMCOL + 17, 4);
+ putint(nbuf, MEMROW + 3, MEMCOL + 30, 8);
+
+ putint(pgtokb(s.uvmexp.active), MEMROW + 5, MEMCOL + 7, 10);
+ putint(pgtokb(s.uvmexp.swpgonly), MEMROW + 5, MEMCOL + 18, 10);
+ putint(pgtokb(s.uvmexp.free), MEMROW + 5, MEMCOL + 28, 10);
+
#undef pgtokb
/* Namei cache */
@@ -633,7 +704,7 @@
putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9);
putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9);
putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9);
- putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9);
+ putint(s.uvmexp.fltnoanon, VMSTATROW + 14, VMSTATCOL, 9);
PUTRATE(s, s1, uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9);
if (LINES - 1 > VMSTATROW + 16)
PUTRATE(s, s1, uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9);
@@ -776,7 +847,7 @@
memset(&stats->nchstats, 0, sizeof(stats->nchstats));
}
if (nintr)
- NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG);
+ NREAD(X_INTRCNT, stats->intrcnt, nintr * sizeof(long));
for (i = 0; i < nevcnt; i++)
KREAD(ie_head[i].ie_count, &stats->evcnt[i],
sizeof stats->evcnt[i]);
--pgp-sign-Multipart_Mon_Dec_10_21:21:06_2018-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit
Content-Description: OpenPGP Digital Signature
-----BEGIN PGP SIGNATURE-----
iF0EABECAB0WIQRuK6dmwVAucmRxuh9mfXG3eL/0fwUCXA9JSAAKCRBmfXG3eL/0
fzQwAJwN021D1fg+U6K8XcHspduxR7kY8gCgzv3YLdrDuJF1AzKlneuhOp16g+A=
=S80n
-----END PGP SIGNATURE-----
--pgp-sign-Multipart_Mon_Dec_10_21:21:06_2018-1--
Home |
Main Index |
Thread Index |
Old Index