cpustat?

YONETANI Tomokazu qhwt+dfly at les.ath.cx
Fri Jun 16 02:52:21 PDT 2006


> Danial Thom wrote:
> > I remember some chatter about cpustat but i don't
> > see it in 1.5.3-PREVIEW, and I don't see that top
> > shows the cpu breakdown. What's the status of
> > this, or what's the utility of choice for
> > monitoring the allocation of cpu resources?
> 
> cpustat is in src/test/pcpu/cpustat.c and yes, it hasn't been merged
> into top yet, maybe you want to do it ;)

No response from Danial because top is too messy to play with? :)
Attached and also available at:
  http://les.ath.cx/DragonFly/top-pcpu.diff

Regards.
diff -r ddfcf59ccfb0 contrib/top/display.c
--- a/contrib/top/display.c	Wed Jun 14 01:45:28 2006 +0000
+++ b/contrib/top/display.c	Fri Jun 16 18:43:33 2006 +0900
@@ -75,7 +75,6 @@ static int num_swap;
 static int num_swap;
 
 static int *lprocstates;
-static int *lcpustates;
 static int *lmemory;
 static int *lswap;
 
@@ -154,7 +153,6 @@ struct statics *statics;
 	num_swap = string_count(swap_names);
 	lswap = (int *)malloc(num_swap * sizeof(int));
 	num_cpustates = string_count(cpustate_names);
-	lcpustates = (int *)malloc(num_cpustates * sizeof(int));
 	cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));
 
 	memory_names = statics->memory_names;
@@ -372,141 +370,68 @@ int *brkdn;
  *  Assumptions:  cursor is on the PREVIOUS line
  */
 
-static int cpustates_column;
-
-/* cpustates_tag() calculates the correct tag to use to label the line */
-
-char *cpustates_tag()
-
-{
-    register char *use;
-
-    static char *short_tag = "CPU: ";
-    static char *long_tag = "CPU states: ";
-
-    /* if length + strlen(long_tag) >= screen_width, then we have to
-       use the shorter tag (we subtract 2 to account for ": ") */
-    if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
-    {
-	use = short_tag;
-    }
-    else
-    {
-	use = long_tag;
-    }
-
-    /* set cpustates_column accordingly then return result */
-    cpustates_column = strlen(use);
-    return(use);
-}
-
-i_cpustates(states)
-
-register int *states;
-
-{
-    register int i = 0;
+void
+i_cpustates(struct system_info *si)
+{
+    register int i;
     register int value;
-    register char **names = cpustate_names;
+    register char **names;
     register char *thisname;
+    int *states = si->cpustates;
+    int cpu;
 
     /* print tag and bump lastline */
-    printf("\n%s", cpustates_tag());
-    lastline++;
-
-    /* now walk thru the names and print the line */
-    while ((thisname = *names++) != NULL)
-    {
-	if (*thisname != '\0')
-	{
-	    /* retrieve the value and remember it */
-	    value = *states++;
-
-	    /* if percentage is >= 1000, print it as 100% */
-	    printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
-		   i++ == 0 ? "" : ", ",
-		   ((float)value)/10.,
-		   thisname);
-	}
-    }
-
-    /* copy over values into "last" array */
-    memcpy(lcpustates, states, num_cpustates * sizeof(int));
-}
-
-u_cpustates(states)
-
-register int *states;
-
-{
-    register int value;
-    register char **names = cpustate_names;
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+	if (n_cpus > 1)
+	    printf("\nCPU%d states: ", cpu);
+	else
+	    printf("\nCPU states: ");
+	lastline++;
+
+	/* now walk thru the names and print the line */
+	names = cpustate_names;
+	i = 0;
+	while ((thisname = *names++) != NULL)
+	{
+	    if (*thisname != '\0')
+	    {
+		/* retrieve the value and remember it */
+		value = *states++;
+		/* if percentage is >= 1000, print it as 100% */
+		printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
+		       i++ == 0 ? "" : ", ",
+		       ((float)value)/10.,
+		       thisname);
+	    }
+	}
+    }
+}
+
+void
+z_cpustates(struct system_info *si)
+{
+    register int i;
+    register char **names;
     register char *thisname;
-    register int *lp;
-    register int *colp;
-
-    Move_to(cpustates_column, y_cpustates);
-    lastline = y_cpustates;
-    lp = lcpustates;
-    colp = cpustate_columns;
-
-    /* we could be much more optimal about this */
-    while ((thisname = *names++) != NULL)
-    {
-	if (*thisname != '\0')
-	{
-	    /* did the value change since last time? */
-	    if (*lp != *states)
-	    {
-		/* yes, move and change */
-		Move_to(cpustates_column + *colp, y_cpustates);
-		lastline = y_cpustates;
-
-		/* retrieve value and remember it */
-		value = *states;
-
-		/* if percentage is >= 1000, print it as 100% */
-		printf((value >= 1000 ? "%4.0f" : "%4.1f"),
-		       ((double)value)/10.);
-
-		/* remember it for next time */
-		*lp = value;
-	    }
-	}
-
-	/* increment and move on */
-	lp++;
-	states++;
-	colp++;
-    }
-}
-
-z_cpustates()
-
-{
-    register int i = 0;
-    register char **names = cpustate_names;
-    register char *thisname;
-    register int *lp;
+    int cpu;
 
     /* show tag and bump lastline */
-    printf("\n%s", cpustates_tag());
-    lastline++;
-
-    while ((thisname = *names++) != NULL)
-    {
-	if (*thisname != '\0')
-	{
-	    printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);
-	}
-    }
-
-    /* fill the "last" array with all -1s, to insure correct updating */
-    lp = lcpustates;
-    i = num_cpustates;
-    while (--i >= 0)
-    {
-	*lp++ = -1;
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+	if (n_cpus > 1)
+	    printf("\nCPU%d states: ", cpu);
+	else
+	    printf("\nCPU states: ");
+	lastline++;
+
+	i = 0;
+	names = cpustate_names;
+	while ((thisname = *names++) != NULL)
+	{
+	    if (*thisname != '\0')
+	    {
+		printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);
+	    }
+	}
     }
 }
 
diff -r ddfcf59ccfb0 contrib/top/layout.h
--- a/contrib/top/layout.h	Wed Jun 14 01:45:28 2006 +0000
+++ b/contrib/top/layout.h	Fri Jun 16 18:43:33 2006 +0900
@@ -16,14 +16,14 @@
 #define  x_brkdn	15
 #define  y_brkdn	1
 #define  x_mem		5
-#define  y_mem		3
+#define  y_mem		(y_cpustates+(smart_terminal?n_cpus:1))
 #define  x_swap		6
-#define  y_swap		4
-#define  y_message	5
+#define  y_swap		(y_mem+1)
+#define  y_message	(y_swap+1)
 #define  x_header	0
-#define  y_header	6
+#define  y_header	(y_message+1)
 #define  x_idlecursor	0
-#define  y_idlecursor	5
-#define  y_procs	7
+#define  y_idlecursor	(y_message)
+#define  y_procs	(y_header+1)
 
 #define  y_cpustates	2
diff -r ddfcf59ccfb0 contrib/top/machine.h
--- a/contrib/top/machine.h	Wed Jun 14 01:45:28 2006 +0000
+++ b/contrib/top/machine.h	Fri Jun 16 18:43:33 2006 +0900
@@ -33,6 +33,7 @@ struct statics
 #define P_ACTIVE p_active
 #endif
 
+/* CPU1 states follow those of CPU0, and so on for SMP */
 struct system_info
 {
     int    last_pid;
diff -r ddfcf59ccfb0 contrib/top/top.c
--- a/contrib/top/top.c	Wed Jun 14 01:45:28 2006 +0000
+++ b/contrib/top/top.c	Fri Jun 16 18:43:33 2006 +0900
@@ -114,8 +114,8 @@ int u_loadave();
 int u_loadave();
 int i_procstates();
 int u_procstates();
-int i_cpustates();
-int u_cpustates();
+int i_cpustates(struct system_info *);
+int u_cpustates(struct system_info *);
 int i_memory();
 int u_memory();
 int i_swap();
@@ -130,13 +130,14 @@ int u_process();
 /* pointers to display routines */
 int (*d_loadave)() = i_loadave;
 int (*d_procstates)() = i_procstates;
-int (*d_cpustates)() = i_cpustates;
+int (*d_cpustates)(struct system_info *) = i_cpustates;
 int (*d_memory)() = i_memory;
 int (*d_swap)() = i_swap;
 int (*d_message)() = i_message;
 int (*d_header)() = i_header;
 int (*d_process)() = i_process;
 
+int n_cpus = 0;
 
 main(argc, argv)
 
@@ -583,14 +584,14 @@ restart:
 	/* display the cpu state percentage breakdown */
 	if (dostates)	/* but not the first time */
 	{
-	    (*d_cpustates)(system_info.cpustates);
+	    (*d_cpustates)(&system_info);
 	}
 	else
 	{
 	    /* we'll do it next time */
 	    if (smart_terminal)
 	    {
-		z_cpustates();
+		z_cpustates(&system_info);
 	    }
 	    else
 	    {
@@ -663,7 +664,7 @@ restart:
 		{
 		    d_loadave = u_loadave;
 		    d_procstates = u_procstates;
-		    d_cpustates = u_cpustates;
+		    d_cpustates = i_cpustates;
 		    d_memory = u_memory;
 		    d_swap = u_swap;
 		    d_message = u_message;
diff -r ddfcf59ccfb0 contrib/top/top.h
--- a/contrib/top/top.h	Wed Jun 14 01:45:28 2006 +0000
+++ b/contrib/top/top.h	Fri Jun 16 18:43:33 2006 +0900
@@ -8,7 +8,8 @@
 #define VERSION		3
 
 /* Number of lines of header information on the standard screen */
-#define Header_lines	7
+#define Header_lines	(7 + n_cpus - 1)
+extern int n_cpus;
 
 /* Maximum number of columns allowed for display */
 #define MAX_COLS	128
diff -r ddfcf59ccfb0 usr.bin/top/machine.c
--- a/usr.bin/top/machine.c	Wed Jun 14 01:45:28 2006 +0000
+++ b/usr.bin/top/machine.c	Fri Jun 16 18:43:33 2006 +0900
@@ -133,7 +133,7 @@ static int ccpu;
 
 /* these are for calculating cpu state percentages */
 
-static struct kinfo_cputime cp_time, cp_old;
+static struct kinfo_cputime *cp_time, *cp_old;
 
 /* these are for detailing the process states */
 
@@ -146,7 +146,7 @@ char *procstatenames[] = {
 
 /* these are for detailing the cpu states */
 #define CPU_STATES 5
-int cpu_states[CPU_STATES];
+int *cpu_states;
 char *cpustatenames[CPU_STATES + 1] = {
     "user", "nice", "system", "interrupt", "idle", NULL
 };
@@ -195,7 +195,6 @@ cputime_percentages(int out[CPU_STATES],
 		    struct kinfo_cputime *old)
 {
         struct kinfo_cputime diffs;
-        int i;
 	uint64_t total_change, half_total;
 
         /* initialization */
@@ -236,6 +235,10 @@ machine_init(struct statics *statics)
     size_t modelen;
     struct passwd *pw;
 
+    if (n_cpus < 1) {
+	if (kinfo_get_cpus(&n_cpus))
+	    err(1, "kinfo_get_cpus failed");
+    }
     modelen = sizeof(smpmode);
     if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
          sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
@@ -322,16 +325,40 @@ get_system_info(struct system_info *si)
     int mib[2];
     struct timeval boottime;
     size_t bt_size;
-
-    if (kinfo_get_sched_cputime(&cp_time))
-	err(1, "kinfo_get_sched_cputime failed");
+    size_t len;
+    int cpu;
+
+    if (cpu_states == NULL) {
+	cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
+	if (cpu_states == NULL)
+	    err(1, "malloc");
+	bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
+    }
+    if (cp_time == NULL) {
+	cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
+	if (cp_time == NULL)
+	    err(1, "cp_time");
+	cp_old = cp_time + n_cpus;
+
+	len = n_cpus * sizeof(cp_old[0]);
+	if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
+	    err(1, "kern.cputime");
+    }
+
+    len = n_cpus * sizeof(cp_time[0]);
+    bzero(cp_time, len);
+    if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
+	err(1, "kern.cputime");
 
     getloadavg(si->load_avg, 3);
 
     lastpid = 0;
 
     /* convert cp_time counts to percentages */
-    cputime_percentages(cpu_states, &cp_time, &cp_old);
+    for (cpu = 0; cpu < n_cpus; ++cpu) {
+	cputime_percentages(cpu_states + cpu * n_cpus, &cp_time[cpu],
+			    &cp_old[cpu]);
+    }
 
     /* sum memory & swap statistics */
     {




More information about the Submit mailing list