Module Name:    src
Committed By:   rin
Date:           Mon Nov 28 08:21:10 UTC 2016

Modified Files:
        src/bin/ps: extern.h print.c ps.c ps.h

Log Message:
Calculate CPU usage (pcpu) once per process if it is required. This change
significantly improves performance for slow machines when output is sorted
by pcpu.

ok martin


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/bin/ps/extern.h
cvs rdiff -u -r1.124 -r1.125 src/bin/ps/print.c
cvs rdiff -u -r1.85 -r1.86 src/bin/ps/ps.c
cvs rdiff -u -r1.27 -r1.28 src/bin/ps/ps.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/ps/extern.h
diff -u src/bin/ps/extern.h:1.36 src/bin/ps/extern.h:1.37
--- src/bin/ps/extern.h:1.36	Mon Nov 28 08:19:23 2016
+++ src/bin/ps/extern.h	Mon Nov 28 08:21:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.36 2016/11/28 08:19:23 rin Exp $	*/
+/*	$NetBSD: extern.h,v 1.37 2016/11/28 08:21:10 rin Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -37,7 +37,7 @@
  */
 
 extern double log_ccpu;
-extern int eval, fscale, mempages, nlistread, rawcpu, maxslp, uspace;
+extern int eval, fscale, mempages, nlistread, maxslp, uspace;
 extern int sumrusage, termwidth, totwidth;
 extern int needenv, needcomm, commandonly;
 extern uid_t myuid;

Index: src/bin/ps/print.c
diff -u src/bin/ps/print.c:1.124 src/bin/ps/print.c:1.125
--- src/bin/ps/print.c:1.124	Mon Nov 28 08:19:23 2016
+++ src/bin/ps/print.c	Mon Nov 28 08:21:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: print.c,v 1.124 2016/11/28 08:19:23 rin Exp $	*/
+/*	$NetBSD: print.c,v 1.125 2016/11/28 08:21:10 rin Exp $	*/
 
 /*
  * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
 #if 0
 static char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
 #else
-__RCSID("$NetBSD: print.c,v 1.124 2016/11/28 08:19:23 rin Exp $");
+__RCSID("$NetBSD: print.c,v 1.125 2016/11/28 08:21:10 rin Exp $");
 #endif
 #endif /* not lint */
 
@@ -1091,33 +1091,14 @@ lcputime(void *arg, VARENT *ve, enum mod
 	cputime1(secs, psecs, v, mode);
 }
 
-double
-getpcpu(const struct kinfo_proc2 *k)
-{
-
-	if (!nlistread)
-		donlist();
-
-#define	fxtofl(fixpt)	((double)(fixpt) / fscale)
-
-	if (k->p_swtime == 0 || k->p_realstat == SZOMB)
-		return (0.0);
-	if (rawcpu)
-		return (100.0 * fxtofl(k->p_pctcpu));
-	return (100.0 * fxtofl(k->p_pctcpu) /
-		(1.0 - exp(k->p_swtime * log_ccpu)));
-}
-
 void
 pcpu(void *arg, VARENT *ve, enum mode mode)
 {
-	struct kinfo_proc2 *k;
 	VAR *v;
 	double dbl;
 
-	k = arg;
 	v = ve->var;
-	dbl = getpcpu(k);
+	dbl = ((struct pinfo *)arg)->pcpu;
 	doubleprintorsetwidth(v, dbl, (dbl >= 99.95) ? 0 : 1, mode);
 }
 

Index: src/bin/ps/ps.c
diff -u src/bin/ps/ps.c:1.85 src/bin/ps/ps.c:1.86
--- src/bin/ps/ps.c:1.85	Mon Nov 28 08:18:27 2016
+++ src/bin/ps/ps.c	Mon Nov 28 08:21:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ps.c,v 1.85 2016/11/28 08:18:27 rin Exp $	*/
+/*	$NetBSD: ps.c,v 1.86 2016/11/28 08:21:10 rin Exp $	*/
 
 /*
  * Copyright (c) 2000-2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@ __COPYRIGHT("@(#) Copyright (c) 1990, 19
 #if 0
 static char sccsid[] = "@(#)ps.c	8.4 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: ps.c,v 1.85 2016/11/28 08:18:27 rin Exp $");
+__RCSID("$NetBSD: ps.c,v 1.86 2016/11/28 08:21:10 rin Exp $");
 #endif
 #endif /* not lint */
 
@@ -89,6 +89,7 @@ __RCSID("$NetBSD: ps.c,v 1.85 2016/11/28
 #include <kvm.h>
 #include <limits.h>
 #include <locale.h>
+#include <math.h>
 #include <nlist.h>
 #include <paths.h>
 #include <pwd.h>
@@ -106,12 +107,10 @@ __RCSID("$NetBSD: ps.c,v 1.85 2016/11/28
 #define	GETOPTSTR	"aAcCeghjk:LlM:mN:O:o:p:rSsTt:U:uvW:wx"
 #define	ARGOPTS		"kMNOopUW"
 
-struct kinfo_proc2 *kinfo;
 struct varlist displaylist = SIMPLEQ_HEAD_INITIALIZER(displaylist);
 struct varlist sortlist = SIMPLEQ_HEAD_INITIALIZER(sortlist);
 
 int	eval;			/* exit value */
-int	rawcpu;			/* -C */
 int	sumrusage;		/* -S */
 int	termwidth;		/* width of screen (0 == infinity) */
 int	totwidth;		/* calculated width of requested variables */
@@ -124,6 +123,8 @@ static struct kinfo_lwp
 		    struct kinfo_lwp *, int);
 static struct kinfo_proc2
 		*getkinfo_kvm(kvm_t *, int, int, int *);
+static struct pinfo
+		*setpinfo(struct kinfo_proc2 *, int, int, int);
 static char	*kludge_oldps_options(char *);
 static int	 pscomp(const void *, const void *);
 static void	 scanvars(void);
@@ -197,12 +198,14 @@ ttyname2dev(const char *ttname, int *xfl
 int
 main(int argc, char *argv[])
 {
+	struct kinfo_proc2 *kinfo;
+	struct pinfo *pinfo;
 	struct varent *vent;
 	struct winsize ws;
 	struct kinfo_lwp *kl, *l;
 	int ch, i, j, fmt, lineno, nentries, nlwps;
 	long long flag;
-	int prtheader, wflag, what, xflg, showlwps;
+	int calc_pcpu, prtheader, wflag, what, xflg, rawcpu, showlwps;
 	char *nlistf, *memf, *swapf, errbuf[_POSIX2_LINE_MAX];
 	char *ttname;
 
@@ -394,11 +397,20 @@ main(int argc, char *argv[])
 
 	/* Add default sort criteria */
 	parsesort("tdev,pid");
+	calc_pcpu = 0;
 	SIMPLEQ_FOREACH(vent, &sortlist, next) {
 		if (vent->var->flag & LWP || vent->var->type == UNSPECIFIED)
 			warnx("Cannot sort on %s, sort key ignored",
 				vent->var->name);
+		if (vent->var->type == PCPU)
+			calc_pcpu = 1;
 	}
+	if (!calc_pcpu)
+		SIMPLEQ_FOREACH(vent, &displaylist, next)
+			if (vent->var->type == PCPU) {
+				calc_pcpu = 1;
+				break;
+			}
 
 	/*
 	 * scan requested variables, noting what structures are needed.
@@ -414,10 +426,12 @@ main(int argc, char *argv[])
 		printheader();
 		return 1;
 	}
+	pinfo = setpinfo(kinfo, nentries, calc_pcpu, rawcpu);
+
 	/*
 	 * sort proc list
 	 */
-	qsort(kinfo, nentries, sizeof(struct kinfo_proc2), pscomp);
+	qsort(pinfo, nentries, sizeof(struct pinfo), pscomp);
 	/*
 	 * For each proc, call each variable output function in
 	 * "setwidth" mode to determine the widest element of
@@ -425,7 +439,8 @@ main(int argc, char *argv[])
 	 */
 
 	for (i = 0; i < nentries; i++) {
-		struct kinfo_proc2 *ki = &kinfo[i];
+		struct pinfo *pi = &pinfo[i];
+		struct kinfo_proc2 *ki = pi->ki;
 
 		if (xflg == 0 && (ki->p_tdev == (uint32_t)NODEV ||
 		    (ki->p_flag & P_CONTROLT) == 0))
@@ -438,7 +453,7 @@ main(int argc, char *argv[])
 		if (showlwps == 0) {
 			l = pick_representative_lwp(ki, kl, nlwps);
 			SIMPLEQ_FOREACH(vent, &displaylist, next)
-				OUTPUT(vent, ki, l, WIDTHMODE);
+				OUTPUT(vent, l, pi, ki, WIDTHMODE);
 		} else {
 			/* The printing is done with the loops
 			 * reversed, but here we don't need that,
@@ -446,7 +461,7 @@ main(int argc, char *argv[])
 			 */
 			SIMPLEQ_FOREACH(vent, &displaylist, next)
 				for (j = 0; j < nlwps; j++)
-					OUTPUT(vent, ki, &kl[j], WIDTHMODE);
+					OUTPUT(vent, &kl[j], pi, ki, WIDTHMODE);
 		}
 	}
 	/*
@@ -460,7 +475,8 @@ main(int argc, char *argv[])
 	 * print mode.
 	 */
 	for (i = lineno = 0; i < nentries; i++) {
-		struct kinfo_proc2 *ki = &kinfo[i];
+		struct pinfo *pi = &pinfo[i];
+		struct kinfo_proc2 *ki = pi->ki;
 
 		if (xflg == 0 && (ki->p_tdev == (uint32_t)NODEV ||
 		    (ki->p_flag & P_CONTROLT ) == 0))
@@ -472,7 +488,7 @@ main(int argc, char *argv[])
 		if (showlwps == 0) {
 			l = pick_representative_lwp(ki, kl, nlwps);
 			SIMPLEQ_FOREACH(vent, &displaylist, next) {
-				OUTPUT(vent, ki, l, PRINTMODE);
+				OUTPUT(vent, l, pi, ki, PRINTMODE);
 				if (SIMPLEQ_NEXT(vent, next) != NULL)
 					(void)putchar(' ');
 			}
@@ -485,7 +501,7 @@ main(int argc, char *argv[])
 		} else {
 			for (j = 0; j < nlwps; j++) {
 				SIMPLEQ_FOREACH(vent, &displaylist, next) {
-					OUTPUT(vent, ki, &kl[j], PRINTMODE);
+					OUTPUT(vent, &kl[j], pi, ki, PRINTMODE);
 					if (SIMPLEQ_NEXT(vent, next) != NULL)
 						(void)putchar(' ');
 				}
@@ -567,6 +583,36 @@ getkinfo_kvm(kvm_t *kdp, int what, int f
 	    nentriesp));
 }
 
+static struct pinfo *
+setpinfo(struct kinfo_proc2 *ki, int nentries, int calc_pcpu, int rawcpu)
+{
+	struct pinfo *pi;
+	int i;
+
+	pi = malloc(nentries * sizeof(struct pinfo));
+	if (pi == NULL)
+		err(1, "malloc");
+
+	if (calc_pcpu && !nlistread)
+		donlist();
+
+	for (i = 0; i < nentries; i++) {
+		pi[i].ki = &ki[i];
+		if (!calc_pcpu)
+			continue;
+		if (ki[i].p_realstat == SZOMB ||
+		    (!rawcpu && ki[i].p_swtime == 0)) {
+			pi[i].pcpu = 0.0;
+			continue;
+		}
+		pi[i].pcpu = 100.0 * (double)ki[i].p_pctcpu / fscale;
+		if (!rawcpu)
+			pi[i].pcpu /= 1.0 - exp(ki[i].p_swtime * log_ccpu);
+	}
+
+	return pi;
+}
+
 static void
 scanvars(void)
 {
@@ -585,8 +631,10 @@ scanvars(void)
 static int
 pscomp(const void *a, const void *b)
 {
-	const struct kinfo_proc2 *ka = (const struct kinfo_proc2 *)a;
-	const struct kinfo_proc2 *kb = (const struct kinfo_proc2 *)b;
+	const struct pinfo *pa = (const struct pinfo *)a;
+	const struct pinfo *pb = (const struct pinfo *)b;
+	const struct kinfo_proc2 *ka = pa->ki;
+	const struct kinfo_proc2 *kb = pb->ki;
 
 	int i;
 	int64_t i64;
@@ -631,8 +679,8 @@ pscomp(const void *a, const void *b)
 		case UINT32:
 			RDIFF(uint32_t);
 		case SIGLIST:
-			sa = (const void *)((const char *)a + v->off);
-			sb = (const void *)((const char *)b + v->off);
+			sa = (const void *)((const char *)ka + v->off);
+			sb = (const void *)((const char *)kb + v->off);
 			i = 0;
 			do {
 				if (sa->__bits[i] > sb->__bits[i])
@@ -666,7 +714,7 @@ pscomp(const void *a, const void *b)
 				return i64 > 0 ? 1 : -1;
 			continue;
 		case PCPU:
-			i = getpcpu(kb) - getpcpu(ka);
+			i = pb->pcpu - pa->pcpu;
 			if (i != 0)
 				return i;
 			continue;

Index: src/bin/ps/ps.h
diff -u src/bin/ps/ps.h:1.27 src/bin/ps/ps.h:1.28
--- src/bin/ps/ps.h:1.27	Sun Apr 20 22:48:59 2014
+++ src/bin/ps/ps.h	Mon Nov 28 08:21:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ps.h,v 1.27 2014/04/20 22:48:59 dholland Exp $	*/
+/*	$NetBSD: ps.h,v 1.28 2016/11/28 08:21:10 rin Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -86,9 +86,16 @@ typedef struct var {
 	double	longestnd;	/* longest negative double */
 } VAR;
 
-#define	OUTPUT(vent, ki, kl, mode) do {					\
+struct pinfo {
+	struct kinfo_proc2 *ki;
+	double pcpu;
+};
+
+#define	OUTPUT(vent, kl, pi, ki, mode) do {				\
 	if ((vent)->var->flag & LWP)					\
 		((vent)->var->oproc)((void *)(kl), (vent), (mode));	\
+	else if ((vent)->var->type == PCPU)				\
+		((vent)->var->oproc)((void *)(pi), (vent), (mode));	\
 	else								\
 		((vent)->var->oproc)((void *)(ki), (vent), (mode));	\
 	} while (/*CONSTCOND*/ 0)

Reply via email to