Date: Fri, 6 Oct 2000 17:16:59 -0700 (PDT) From: Romain Kang <romain@kzsu.stanford.edu> To: rh@matriplex.com Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: A decent way to get CPU idle time? Message-ID: <200010070016.RAA17529@kzsu.stanford.edu>
next in thread | raw e-mail | index | archive | help
I am loathe to call kmem readers clean and decent, but I coincidentally did something similar today, ripping out code from vmstat. See below. It doesn't look difficult to implement a sysctl() interface, but I guess if someone considered the data really important, it would have been done already. IMHO, getloadavg() is flagrantly meaningless. There are plenty of ways to skew the numbers without actually changing CPU activity. Romain Kang Disclaimer: I speak for myself alone, romain@kzsu.stanford.edu except when indicated otherwise. | Is there a clean and decent way to find out the percentage | of CPU idle time, like top and systat give? I have browsed | the source for both, and neither appear to have a simple | way of finding this information. | I have already tried and rejected getloadavg. In my | application, two main processes will always account | for 95% or more of the activity. | I suppose I could use RDTSC to grab the clock on my system | calls, and figure a rudimentary sum of CPU activity, but | that won't help me with the expensive file and socket calls. | And I would pretty much have to guess about the CPU time spent | in the kernel. | Any ideas? Thanks. #include <sys/param.h> #include <sys/dkstat.h> #include <kvm.h> #include <nlist.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> struct nlist namelist[] = { #define X_CPTIME 0 { "_cp_time" }, {""} }; char *nlistf = NULL, *memf = NULL; kvm_t *kd; void kread(); void cpu_init(); void cpu_idle(); main() { cpu_init(); cpu_idle(); } void cpu_init() { int c; static char errbuf[BUFSIZ]; /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) setgid(getgid()); kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); if (kd == 0) errx(1, "kvm_openfiles: %s", errbuf); if ((c = kvm_nlist(kd, namelist)) != 0) { if (c > 0) { warnx("undefined symbols:"); for (c = 0; c < sizeof(namelist)/sizeof(namelist[0]); c++) if (namelist[c].n_type == 0) fprintf(stderr, " %s", namelist[c].n_name); (void)fputc('\n', stderr); } else warnx("kvm_nlist: %s", kvm_geterr(kd)); exit(1); } } void cpu_idle() { register int state; double pct, total; long cp_time[CPUSTATES]; int idle_percent; kread(X_CPTIME, cp_time, sizeof(cp_time)); total = 0; for (state = 0; state < CPUSTATES; ++state) total += cp_time[state]; if (total) pct = 100 / total; else pct = 0; idle_percent = cp_time[CP_IDLE] * pct; printf("idle%%=%d\n", idle_percent); } /* * kread reads something from the kernel, given its nlist index. */ void kread(nlx, addr, size) int nlx; void *addr; size_t size; { char *sym; if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { sym = namelist[nlx].n_name; if (*sym == '_') ++sym; errx(1, "symbol %s not defined", sym); } if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { sym = namelist[nlx].n_name; if (*sym == '_') ++sym; errx(1, "%s: %s", sym, kvm_geterr(kd)); } } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010070016.RAA17529>