[meego-commits] 9021: Changes to Trunk/bootchart

Peter Zhu no_reply at build.meego.com
Thu Oct 28 14:10:06 UTC 2010


Hi,
I have made the following changes to bootchart in project Trunk. Please review and accept ASAP.

Thank You,
Peter Zhu

[This message was auto-generated]

---

Request #9021:

  submit:   Trunk:Testing/bootchart(r7) -> Trunk/bootchart


Message:
    Move to Trunk

State:   new          2010-10-28T07:10:06 peter
Comment: None



changes files:
--------------
--- bootchart.changes
+++ bootchart.changes
@@ -0,0 +1,11 @@
+* Tue Oct 26 2010 Auke Kok <auke-jan.h.kok at intel.com> - 1.8
+- BMC#7222 - Massive performance overhaul: reduce syscall load by 60%.
+
+* Tue Oct 26 2010 Auke Kok <auke-jan.h.kok at intel.com> - 1.7
+- Fix install of example config
+- Install README/COPYING
+- Double samples to 8192 for now
+
+* Mon Oct 25 2010 Auke Kok <auke-jan.h.kok at intel.com> - 1.5
+- implement reading a conf file in /etc/.
+

old:
----
  bootchart-1.3.tar.gz

new:
----
  bootchart-1.8.tar.gz

spec files:
-----------
--- bootchart.spec
+++ bootchart.spec
@@ -1,20 +1,21 @@
 # 
-# Do not Edit! Generated by:
-# spectacle version 0.14
+# Do NOT Edit the Auto-generated Part!
+# Generated by: spectacle version 0.20
 # 
 # >> macros
 # << macros
 
 Name:       bootchart
 Summary:    Boot time graph generator
-Version:    1.3
+Version:    1.8
 Release:    1
 Group:      Applications/System
 License:    GPLv2
-URL:        http://www.moblin.org/
+URL:        http://meego.gitorious.org/
 Source0:    http://moblin.org/bootchart-%{version}.tar.gz
 Source100:  bootchart.yaml
 
+
 %description
 Monitors where the system spends its time at start, creating a graph of all processes, disk utilization, and wait time.
 
@@ -51,8 +52,11 @@
 
 %files
 %defattr(-,root,root,-)
+/sbin/bootchartd
+/usr/share/doc/bootchart/bootchartd.conf.example
+/usr/share/doc/bootchart/COPYING
+/usr/share/doc/bootchart/README
 # >> files
-%attr(0755,root,root) /sbin/bootchartd
 # << files
 
 

other changes:
--------------

++++++ bootchart-1.3.tar.gz -> bootchart-1.8.tar.gz
--- Makefile
+++ Makefile
@@ -1,5 +1,5 @@
 
-VERSION = 1.3
+VERSION = 1.8
 
 CC := gcc
 
@@ -7,7 +7,11 @@
 
 install: bootchartd
 	mkdir -p $(DESTDIR)/sbin
-	install bootchartd $(DESTDIR)/sbin/
+	mkdir -p $(DESTDIR)/etc
+	mkdir -p $(DESTDIR)/usr/share/doc/bootchart/
+	install -m0755 bootchartd $(DESTDIR)/sbin/
+	install -m0644 bootchartd.conf.example $(DESTDIR)/usr/share/doc/bootchart/
+	install -m0644 README COPYING $(DESTDIR)/usr/share/doc/bootchart/
 
 OBJS := log.o svg.o bootchart.o
 
--- README
+++ README
@@ -59,6 +59,20 @@
 
 --
 
-For bugs, please contac the author or current maintainer:
+Configuration: please see bootchartd --help, as well as /etc/bootchartd.conf
+and/or /usr/share/doc/bootchart/bootchartd.conf.example for a list of
+configurable options.
+
+--
+
+Many thanks to those who contributed ideas and code:
+ - Ziga Mahkovec - Original bootchart author
+ - Anders Norgaard - PyBootchartgui
+ - Michael Meeks - bootchart2
+ - Scott James Remnant - Ubuntu C-based logger
+
+--
+
+For bugs, please contact the author or current maintainer:
 Auke Kok <auke-jan.h.kok at intel.com>
 
--- bootchart.c
+++ bootchart.c
@@ -60,9 +60,48 @@
 	char output_file[PATH_MAX];
 	char datestr[200];
 	time_t t;
+	FILE *f;
 
 	memset(&t, 0, sizeof(time_t));
 
+	f = fopen("/etc/bootchartd.conf", "r");
+	if (f) {
+		char buf[256];
+		char *key;
+		char *val;
+
+		while (fgets(buf, 80, f) != NULL) {
+			char *c;
+
+			c = strchr(buf, '\n');
+			if (c) *c = 0; /* remove trailing \n */
+
+			if (buf[0] == '#')
+				continue; /* comment line */
+
+			key = strtok(buf, "=");
+			if (!key)
+				continue;
+			val = strtok(NULL, "=");
+			if (!val)
+				continue;
+
+			// todo: filter leading/trailing whitespace
+
+			if (!strcmp(key, "samples"))
+				len = atoi(val);
+			if (!strcmp(key, "freq"))
+				hz = atoi(val);
+			if (!strcmp(key, "rel"))
+				relative = atoi(val);;
+			if (!strcmp(key, "filter"))
+				filter = atoi(val);;
+			if (!strcmp(key, "output"))
+				strncpy(output_path, val, PATH_MAX - 1);
+		}
+		fclose(f);
+	}
+
 	while (1) {
 		static struct option opts[] = {
 			{"rel", 0, NULL, 'r'},
@@ -91,10 +130,6 @@
 			break;
 		case 'n':
 			len = atoi(optarg);
-			if (len > MAXSAMPLES) {
-				fprintf(stderr, "Error: samples exceeds maximum\n");
-				exit(EXIT_FAILURE);
-			}
 			break;
 		case 'o':
 			strncpy(output_path, optarg, PATH_MAX - 1);
@@ -108,13 +143,18 @@
 			fprintf(stderr, " --filter,  -F            Disable filtering of processes from the graph\n");
 			fprintf(stderr, "                          that are of less importance or short-lived\n");
 			fprintf(stderr, " --help,    -h            Display this message\n");
-			exit (EXIT_FAILURE);
+			fprintf(stderr, "See the installed README and bootchartd.conf.example for more information.\n");
+			exit (EXIT_SUCCESS);
 			break;
 		default:
 			break;
 		}
 	}
 
+	if (len > MAXSAMPLES) {
+		fprintf(stderr, "Error: samples exceeds maximum\n");
+		exit(EXIT_FAILURE);
+	}
 
 	/*
 	 * If the kernel executed us through init=/sbin/bootchartd, then
--- bootchart.h
+++ bootchart.h
@@ -16,7 +16,7 @@
 
 #define MAXCPUS         8
 #define MAXPIDS     65535
-#define MAXSAMPLES   4096
+#define MAXSAMPLES   8192
 
 
 struct block_stat_struct {
@@ -53,6 +53,10 @@
 	int pid;
 	int ppid;
 
+	/* cache fd's */
+	int sched;
+	int schedstat;
+
 	/* index to first/last seen timestamps */
 	int first;
 	int last;
--- bootchartd.conf.example
+++ bootchartd.conf.example
+#
+# bootchartd configuration - /etc/bootchartd.conf
+#
+# defaults are:
+#
+#len=500
+#freq=25
+#relative=0
+#filter=1
+#output=<dynamic name, in /var/log/bootchart-$TIMESTAMP.svg>
--- log.c
+++ log.c
@@ -11,11 +11,18 @@
  * of the License.
  */
 
-#include <time.h>
-#include <stdio.h>
+#define _GNU_SOURCE 1
+#include <unistd.h>
 #include <stdlib.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
 #include <string.h>
 #include <dirent.h>
+#include <fcntl.h>
+#include <time.h>
+
 
 #include "bootchart.h"
 
@@ -57,55 +64,90 @@
 }
 
 
+static char *bufgetline(char *buf)
+{
+	char *c;
+
+	if (!buf)
+		return NULL;
+
+	c = strchr(buf, '\n');
+	if (c)
+		c++;
+	return c;
+}
+
+
 void log_sample(int sample)
 {
-	FILE *f;
-	DIR *proc;
+	static int vmstat;
+	static int schedstat;
+	static DIR *proc;
+	FILE *stat;
+	char buf[4095];
 	char key[256];
 	char val[256];
 	char rt[256];
 	char wt[256];
+	char *m;
 	int c;
 	int p;
+	int s;
+	int n;
 	struct dirent *ent;
 
+	if (!vmstat) {
+		/* block stuff */
+		vmstat = open("/proc/vmstat", O_RDONLY);
+		if (!vmstat) {
+			perror("open /proc/vmstat");
+			exit (EXIT_FAILURE);
+		}
+	}
 
-	/* block stuff */
-	f = fopen("/proc/vmstat", "r");
-	if (!f) {
-		perror("fopen(\"/proc/vmstat\")");
-		exit (EXIT_FAILURE);
+	n = pread(vmstat, buf, sizeof(buf) - 1, 0);
+	if (n <= 0) {
+		close(vmstat);
+		return;
 	}
+	buf[n] = '\0';
 
-	while (fscanf(f, "%s %s", key, val) > 0) {
+	m = buf;
+	while (m) {
+		if (sscanf(m, "%s %s", key, val) < 2)
+			goto vmstat_next;
 		if (!strcmp(key, "pgpgin"))
 			blockstat[sample].bi = atoi(val);
 		if (!strcmp(key, "pgpgout")) {
 			blockstat[sample].bo = atoi(val);
 			break;
 		}
+vmstat_next:
+		m = bufgetline(m);
+		if (!m)
+			break;
 	}
 
-	fclose(f);
-
-	/* overall CPU utilization */
-	f = fopen("/proc/schedstat", "r");
-	if (!f) {
-		perror("fopen(\"/proc/schedstat\")");
-		exit (EXIT_FAILURE);
+	if (!schedstat) {
+		/* overall CPU utilization */
+		schedstat = open("/proc/schedstat", O_RDONLY);
+		if (!schedstat) {
+			perror("open /proc/schedstat");
+			exit (EXIT_FAILURE);
+		}
 	}
 
-	while (!feof(f)) {
-		int n;
-		char line[4096];
-
-		if (!fgets(line, 4095, f))
-			continue;
-
-		n = sscanf(line, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt);
+	n = pread(schedstat, buf, sizeof(buf) - 1, 0);
+	if (n <= 0) {
+		close(schedstat);
+		return;
+	}
+	buf[n] = '\0';
 
-		if (n < 3)
-			continue;
+	m = buf;
+	while (m) {
+		if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3)
+			goto schedstat_next;
 
 		if (strstr(key, "cpu")) {
 			c = key[3] - '0';
@@ -115,14 +157,21 @@
 			if (c == cpus)
 				cpus = c + 1;
 		}
+schedstat_next:
+		m = bufgetline(m);
+		if (!m)
+			break;
 	}
 
-	fclose(f);
-
-	/* find all processes */
-	proc = opendir("/proc");
-	if (!proc)
-		return;
+	/* all the per-process stuff goes here */
+	if (!proc) {
+		/* find all processes */
+		proc = opendir("/proc");
+		if (!proc)
+			return;
+	} else {
+		rewinddir(proc);
+	}
 
 	while ((ent = readdir(proc)) != NULL) {
 		char filename[PATH_MAX];
@@ -136,19 +185,7 @@
 		if (pid > MAXPIDS)
 			continue;
 
-		sprintf(filename, "/proc/%d/schedstat", pid);
-
-		f = fopen(filename, "r");
-		if (!f)
-			continue;
-		if (!fscanf(f, "%s %s %*s", rt, wt)) {
-			fclose(f);
-			continue;
-		}
-		fclose(f);
-
 		if (!ps[pid]) {
-			char line[80];
 			char t[32];
 			struct ps_struct *parent;
 
@@ -166,49 +203,47 @@
 			ps[pid]->first = sample;
 
 			/* get name, start time */
-			sprintf(filename, "/proc/%d/sched", pid);
-			f = fopen(filename, "r");
-			if (!f)
-				continue;
+			if (!ps[pid]->sched) {
+				sprintf(filename, "/proc/%d/sched", pid);
+				ps[pid]->sched = open(filename, O_RDONLY);
+				if (!ps[pid]->sched)
+					continue;
+			}
 
-			if (!fgets(line, 79, f)) {
-				fclose(f);
+			s = pread(ps[pid]->sched, buf, sizeof(buf) - 1, 0);
+			if (s <= 0) {
+				close(ps[pid]->sched);
 				continue;
 			}
-			if (!sscanf(line, "%s %*s %*s", key)) {
-				fclose(f);
+
+			if (!sscanf(buf, "%s %*s %*s", key))
 				continue;
-			}
 
 			strncpy(ps[pid]->name, key, 16);
 			/* discard line 2 */
-			if (!fgets(line, 79, f)) {
-				fclose(f);
+			m = bufgetline(buf);
+			if (!m)
 				continue;
-			}
 
-			if (!fgets(line, 79, f)) {
-				fclose(f);
+			m = bufgetline(m);
+			if (!m)
 				continue;
-			}
-			if (!sscanf(line, "%*s %*s %s", t)) {
-				fclose(f);
+
+			if (!sscanf(m, "%*s %*s %s", t))
 				continue;
-			}
-			fclose(f);
 
 			ps[pid]->starttime = strtod(t, NULL) / 1000.0;
 
 			/* ppid */
 			sprintf(filename, "/proc/%d/stat", pid);
-			f = fopen(filename, "r");
-			if (!f)
+			stat = fopen(filename, "r");
+			if (!stat)
 				continue;
-			if (!fscanf(f, "%*s %*s %*s %i", &p)) {
-				fclose(f);
+			if (!fscanf(stat, "%*s %*s %*s %i", &p)) {
+				fclose(stat);
 				continue;
 			}
-			fclose(f);
+			fclose(stat);
 			ps[pid]->ppid = p;
 
 			/*
@@ -239,9 +274,21 @@
 					children = children->next;
 				children->next = ps[pid];
 			}
+		}
 
+		if (!ps[pid]->schedstat) {
+			sprintf(filename, "/proc/%d/schedstat", pid);
+			ps[pid]->schedstat = open(filename, O_RDONLY);
+			if (!ps[pid]->schedstat)
+				continue;
+		}
 
+		if (pread(ps[pid]->schedstat, buf, sizeof(buf) - 1, 0) <= 0) {
+			close(ps[pid]->schedstat);
+			continue;
 		}
+		if (!sscanf(buf, "%s %s %*s", rt, wt))
+			continue;
 
 		ps[pid]->pid = pid;
 		ps[pid]->last = sample;
@@ -254,29 +301,25 @@
 
 		/* catch process rename, try to randomize time */
 		if (((samples - ps[pid]->first) + pid) % (hz / 4) == 0) {
-			char line[80];
 
 			/* re-fetch name */
-			sprintf(filename, "/proc/%d/sched", pid);
-			f = fopen(filename, "r");
-
-			if (!fgets(line, 79, f)) {
-				fclose(f);
-				continue;
+			/* get name, start time */
+			if (!ps[pid]->sched) {
+				sprintf(filename, "/proc/%d/sched", pid);
+				ps[pid]->sched = open(filename, O_RDONLY);
+				if (!ps[pid]->sched)
+					continue;
 			}
-			if (!sscanf(line, "%s %*s %*s", key)) {
-				fclose(f);
+			if (pread(ps[pid]->sched, buf, sizeof(buf) - 1, 0) <= 0) {
+				close(ps[pid]->sched);
 				continue;
 			}
 
-			strncpy(ps[pid]->name, key, 16);
-			fclose(f);
+			if (!sscanf(buf, "%s %*s %*s", key))
+				continue;
 
+			strncpy(ps[pid]->name, key, 16);
 		}
-
 	}
-
-	// FIXME: why does this give glibc double free or crap?
-	closedir(proc);
 }
 

++++++ bootchart.yaml
--- bootchart.yaml
+++ bootchart.yaml
@@ -1,10 +1,10 @@
 Name: bootchart
 Summary: Boot time graph generator
-Version: 1.3
+Version: 1.8
 Release: 1
 Group: Applications/System
 License: GPLv2
-URL: http://www.moblin.org/
+URL: http://meego.gitorious.org/
 Description:
     Monitors where the system spends its time at start, creating a graph
     of all processes, disk utilization, and wait time.
@@ -12,3 +12,9 @@
     - http://moblin.org/bootchart-%{version}.tar.gz
 
 Configure: none
+Files:
+    - "/sbin/bootchartd"
+    - "/usr/share/doc/bootchart/bootchartd.conf.example"
+    - "/usr/share/doc/bootchart/COPYING"
+    - "/usr/share/doc/bootchart/README"
+




More information about the MeeGo-commits mailing list