Below is a utility which outputs utilization CPU by domain and by phys
CPU. We used this for some OLS work last year, and we have received
some requests for the patch. We needed this utility because we wanted
to know which and how much of a phys CPU a domain was consuming, and we
wanted output to be easily redirected to a text file, to be processed
later.
This patch is quite old (and very rough on the edges), but it should
still apply to current xen-unstable. It was originally based off xentop
code (I am certain there are many lines in there, originally for xentop,
which are not even needed for vm-stat). I should also state that its
ability to attribute a domain's vCPU time to a pCPU is not very accurate
anymore with the addition of credit scheduler and load balancing. When
we did not load balance, it was pretty easy to assume a vCPU's time was
all spent on one pCPU -not the case anymore. If you want accurate
vCPU->pCPU usage, I think we would need some additional data in vcpu
struct, or just pin vCPUs to pCPUS for your tests.
I am not sure if this utility is of any use to anyone these days, but I
wanted to make it available just in case. I am not asking to have this
included in xen, but if someone else finds it useful and wants to clean
it up, have fun!
-Andrew
<signed-off-by: Andrew Theurer habanero@xxxxxxxxxx>
diff -Naurp 1/tools/xenstat/libxenstat/src/xenstat.c
2/tools/xenstat/libxenstat/src/xenstat.c
--- 1/tools/xenstat/libxenstat/src/xenstat.c 2005-10-26 11:07:15.000000000
-0500
+++ 2/tools/xenstat/libxenstat/src/xenstat.c 2005-10-26 14:30:41.000000000
-0500
@@ -63,6 +63,7 @@ struct xenstat_domain {
struct xenstat_vcpu {
unsigned int online;
unsigned long long ns;
+ int phys_cpu;
};
struct xenstat_network {
@@ -451,6 +452,7 @@ static int xenstat_collect_vcpus(xenstat
node->domains[i].vcpus[vcpu].online = info.online;
node->domains[i].vcpus[vcpu].ns = info.cpu_time;
+ node->domains[i].vcpus[vcpu].phys_cpu = info.cpu;
}
}
return 1;
@@ -475,6 +477,12 @@ unsigned int xenstat_vcpu_online(xenstat
return vcpu->online;
}
+/* Get VCPU to PHYSCPU mapping */
+int xenstat_vcpu_physcpu(xenstat_vcpu * vcpu)
+{
+ return vcpu->phys_cpu;
+}
+
/* Get VCPU usage */
unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
{
diff -Naurp 1/tools/xenstat/libxenstat/src/xenstat.h
2/tools/xenstat/libxenstat/src/xenstat.h
--- 1/tools/xenstat/libxenstat/src/xenstat.h 2005-10-26 11:07:15.000000000
-0500
+++ 2/tools/xenstat/libxenstat/src/xenstat.h 2005-10-26 11:08:46.000000000
-0500
@@ -118,6 +118,9 @@ xenstat_network *xenstat_domain_network(
* VCPU functions - extract information from a xenstat_vcpu
*/
+/* Get VCPU to PHYSCPU mapping */
+int xenstat_vcpu_physcpu(xenstat_vcpu * vcpu);
+
/* Get VCPU usage */
unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu);
unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu);
diff -Naurp 1/tools/xenstat/Makefile 2/tools/xenstat/Makefile
--- 1/tools/xenstat/Makefile 2005-10-26 15:05:50.000000000 -0500
+++ 2/tools/xenstat/Makefile 2005-10-26 11:08:46.000000000 -0500
@@ -6,7 +6,7 @@ SUBDIRS += libxenstat
# This doesn't cross-compile (cross-compile environments rarely have curses)
ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
-SUBDIRS += xentop
+SUBDIRS += xentop vm-stat
endif
.PHONY: all install clean
diff -Naurp 1/tools/xenstat/vm-stat/Makefile 2/tools/xenstat/vm-stat/Makefile
--- 1/tools/xenstat/vm-stat/Makefile 1969-12-31 18:00:00.000000000 -0600
+++ 2/tools/xenstat/vm-stat/Makefile 2005-10-26 11:08:46.000000000 -0500
@@ -0,0 +1,43 @@
+# Copyright (C) International Business Machines Corp., 2005
+# Author: Josh Triplett <josht@xxxxxxxxxx>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; under version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+XEN_ROOT=../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+ifneq ($(XENSTAT_XENTOP),y)
+all install vm-stat:
+else
+
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755 -D
+INSTALL_DATA = $(INSTALL) -m0644 -D
+
+prefix=/usr
+mandir=$(prefix)/share/man
+man1dir=$(mandir)/man1
+sbindir=$(prefix)/sbin
+
+CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
+LDFLAGS += -L$(XEN_LIBXENSTAT)
+LDLIBS += -lxenstat -lncurses
+
+all: vm-stat
+
+vm-stat: vm-stat.o
+
+install: vm-stat
+ $(INSTALL_PROG) vm-stat $(DESTDIR)$(sbindir)/vm-stat
+
+endif
+
+clean:
+ rm -f vm-stat vm-stat.o
diff -Naurp 1/tools/xenstat/vm-stat/vm-stat.c 2/tools/xenstat/vm-stat/vm-stat.c
--- 1/tools/xenstat/vm-stat/vm-stat.c 1969-12-31 18:00:00.000000000 -0600
+++ 2/tools/xenstat/vm-stat/vm-stat.c 2005-10-26 11:08:46.000000000 -0500
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2005
+ * Author(s): Judy Fischbach <jfisch@xxxxxxxxxx>
+ * David Hendricks <dhendrix@xxxxxxxxxx>
+ * Josh Triplett <josht@xxxxxxxxxx>
+ * based on code from Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <curses.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <xenstat.h>
+
+#define KEY_ESCAPE '\x1B'
+
+/*
+ * Function prototypes
+ */
+/* Utility functions */
+static void cleanup(void);
+static void fail(const char *);
+
+/* Section printing functions */
+static void top(void);
+
+
+/* Globals */
+struct timeval curtime, oldtime;
+xenstat_handle *xhandle = NULL;
+xenstat_node *prev_node = NULL;
+xenstat_node *cur_node = NULL;
+unsigned int delay = 3;
+
+/* Clean up any open resources */
+static void cleanup(void)
+{
+ if(prev_node != NULL)
+ xenstat_free_node(prev_node);
+ if(cur_node != NULL)
+ xenstat_free_node(cur_node);
+ if(xhandle != NULL)
+ xenstat_uninit(xhandle);
+}
+
+/* Display the given message and gracefully exit */
+static void fail(const char *str)
+{
+ fprintf(stderr, str);
+ exit(1);
+}
+
+static void top(void)
+{
+ xenstat_domain *cur_domain, *prev_domain;
+ unsigned int i, j, phys_cpu, num_domains = 0, num_vcpus;
+ xenstat_vcpu *prev_vcpu, *cur_vcpu;
+ unsigned long long vcpu_ns;
+ double us_elapsed;
+ typedef struct {
+ unsigned long long ns;
+ char detail[320];
+ int len;
+ } phys_cpu_t;
+
+ phys_cpu_t cpu[64];
+
+ double vcpu_pct;
+
+ for (i = 0; i < 64; i++) {
+ cpu[i].ns = 0;
+ cpu[i].len = 0;
+ }
+
+ prev_node = cur_node;
+ cur_node = xenstat_get_node(xhandle, XENSTAT_ALL);
+ if (cur_node == NULL)
+ fail("Failed to retrieve statistics from libxenstat\n");
+
+ /* Wait until we have 2 samples */
+ if (prev_node == NULL)
+ return;
+
+ printf("\nCPU Total Pct Virtual CPUs\n");
+ /* Count the number of domains for which to report data */
+ num_domains = xenstat_node_num_domains(cur_node);
+
+ us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0
+ + (curtime.tv_usec - oldtime.tv_usec));
+
+ for (i=0; i < num_domains; i++) {
+ cur_domain = xenstat_node_domain_by_index(cur_node, i);
+ prev_domain = xenstat_node_domain_by_index(prev_node, i);
+
+ if (prev_domain && cur_domain) {
+ unsigned int dom_id;
+ dom_id = xenstat_domain_id(cur_domain);
+ num_vcpus = xenstat_domain_num_vcpus(cur_domain);
+ for (j = 0; j < num_vcpus; j++) {
+ cur_vcpu = xenstat_domain_vcpu(cur_domain, j);
+ prev_vcpu = xenstat_domain_vcpu(prev_domain, j);
+ if (cur_vcpu >= 0 && prev_vcpu >= 0) {
+ phys_cpu =
xenstat_vcpu_physcpu(cur_vcpu);
+ vcpu_ns = xenstat_vcpu_ns(cur_vcpu) -
xenstat_vcpu_ns(prev_vcpu);
+ vcpu_pct = vcpu_ns / 10.0 / us_elapsed;
+ cpu[phys_cpu].ns += vcpu_ns;
+ cpu[phys_cpu].len +=
sprintf(&cpu[phys_cpu].detail[cpu[phys_cpu].len], " d%u-%u[%05.1f]", dom_id, j,
vcpu_pct);
+
+ }
+ }
+ }
+ }
+ for (i = 0; i < 64; i++) {
+ double pct;
+ if (cpu[i].ns > 0) {
+
+ pct = cpu[i].ns / 10.0 / us_elapsed;
+ printf("%3i [%05.1f] %s\n", i, pct, cpu[i].detail);
+ fflush(NULL);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc >= 2) {
+ delay = atoi(argv[1]);
+ }
+ if (atexit(cleanup) != 0)
+ fail("Failed to install cleanup handler.\n");
+
+ /* Get xenstat handle */
+ xhandle = xenstat_init();
+ if (xhandle == NULL)
+ fail("Failed to initialize xenstat library\n");
+
+ do {
+ gettimeofday(&curtime, NULL);
+ top();
+ oldtime = curtime;
+ sleep(delay);
+ } while (0 == 0);
+
+ /* Cleanup occurs in cleanup(), so no work to do here. */
+
+ return 0;
+}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|