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
This commit is contained in:
parent
b095bb75a7
commit
cc1877ba3a
|
@ -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;
|
||||
|
|
|
@ -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 mode mode)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
82
bin/ps/ps.c
82
bin/ps/ps.c
|
@ -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, 1993, 1994\
|
|||
#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 08:18:27 rin Exp $");
|
|||
#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 08:18:27 rin Exp $");
|
|||
#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 *xflg, int *what)
|
|||
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 flag, int *nentriesp)
|
|||
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;
|
||||
|
|
11
bin/ps/ps.h
11
bin/ps/ps.h
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue