[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