diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/bootchart/bootchart.c | 127 | ||||
-rw-r--r-- | src/bootchart/bootchart.h | 39 | ||||
-rw-r--r-- | src/bootchart/store.c | 57 | ||||
-rw-r--r-- | src/bootchart/store.h | 34 | ||||
-rw-r--r-- | src/bootchart/svg.c | 173 | ||||
-rw-r--r-- | src/bootchart/svg.h | 27 |
7 files changed, 243 insertions, 215 deletions
diff --git a/Makefile.am b/Makefile.am index f0fe5872cd..c8f7b8e1df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2878,6 +2878,7 @@ systemd_bootchart_SOURCES = \ src/bootchart/bootchart.c \ src/bootchart/bootchart.h \ src/bootchart/store.c \ + src/bootchart/store.h \ src/bootchart/svg.c systemd_bootchart_LDADD = \ diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index 65f16c517c..a722b2aabf 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -1,5 +1,7 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + /*** - bootchart.c - This file is part of systemd-bootchart + This file is part of systemd. Copyright (C) 2009-2013 Intel Coproration @@ -47,14 +49,15 @@ #include <fcntl.h> #include <stdbool.h> - -#include "bootchart.h" #include "util.h" #include "fileio.h" #include "macro.h" #include "conf-parser.h" #include "strxcpyx.h" #include "path-util.h" +#include "store.h" +#include "svg.h" +#include "bootchart.h" double graph_start; double log_start; @@ -72,33 +75,30 @@ static int exiting = 0; int sysfd=-1; /* graph defaults */ -bool entropy = false; +bool arg_entropy = false; bool initcall = true; -bool relative = false; -bool filter = true; -bool show_cmdline = false; -bool pss = false; +bool arg_relative = false; +bool arg_filter = true; +bool arg_show_cmdline = false; +bool arg_pss = false; int samples; -int samples_len = 500; /* we record len+1 (1 start sample) */ -double hz = 25.0; /* 20 seconds log time */ -double scale_x = 100.0; /* 100px = 1sec */ -double scale_y = 20.0; /* 16px = 1 process bar */ +int arg_samples_len = 500; /* we record len+1 (1 start sample) */ +double arg_hz = 25.0; /* 20 seconds log time */ +double arg_scale_x = 100.0; /* 100px = 1sec */ +double arg_scale_y = 20.0; /* 16px = 1 process bar */ -char init_path[PATH_MAX] = "/sbin/init"; -char output_path[PATH_MAX] = "/run/log"; +char arg_init_path[PATH_MAX] = "/sbin/init"; +char arg_output_path[PATH_MAX] = "/run/log"; static struct rlimit rlim; -static void signal_handler(int sig) -{ +static void signal_handler(int sig) { if (sig++) sig--; exiting = 1; } - -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { _cleanup_free_ char *build = NULL; struct sigaction sig; struct ps_struct *ps; @@ -112,16 +112,16 @@ int main(int argc, char *argv[]) char *init = NULL, *output = NULL; const ConfigTableItem items[] = { - { "Bootchart", "Samples", config_parse_int, 0, &samples_len }, - { "Bootchart", "Frequency", config_parse_double, 0, &hz }, - { "Bootchart", "Relative", config_parse_bool, 0, &relative }, - { "Bootchart", "Filter", config_parse_bool, 0, &filter }, - { "Bootchart", "Output", config_parse_path, 0, &output }, - { "Bootchart", "Init", config_parse_path, 0, &init }, - { "Bootchart", "PlotMemoryUsage", config_parse_bool, 0, &pss }, - { "Bootchart", "PlotEntropyGraph", config_parse_bool, 0, &entropy }, - { "Bootchart", "ScaleX", config_parse_double, 0, &scale_x }, - { "Bootchart", "ScaleY", config_parse_double, 0, &scale_y }, + { "Bootchart", "Samples", config_parse_int, 0, &arg_samples_len }, + { "Bootchart", "Frequency", config_parse_double, 0, &arg_hz }, + { "Bootchart", "Relative", config_parse_bool, 0, &arg_relative }, + { "Bootchart", "Filter", config_parse_bool, 0, &arg_filter }, + { "Bootchart", "Output", config_parse_path, 0, &output }, + { "Bootchart", "Init", config_parse_path, 0, &init }, + { "Bootchart", "PlotMemoryUsage", config_parse_bool, 0, &arg_pss }, + { "Bootchart", "PlotEntropyGraph", config_parse_bool, 0, &arg_entropy }, + { "Bootchart", "ScaleX", config_parse_double, 0, &arg_scale_x }, + { "Bootchart", "ScaleY", config_parse_double, 0, &arg_scale_y }, { NULL, NULL, NULL, 0, NULL } }; @@ -137,9 +137,9 @@ int main(int argc, char *argv[]) log_warning("Failed to parse configuration file: %s", strerror(-r)); if (init != NULL) - strscpy(init_path, sizeof(init_path), init); + strscpy(arg_init_path, sizeof(arg_init_path), init); if (output != NULL) - strscpy(output_path, sizeof(output_path), output); + strscpy(arg_output_path, sizeof(arg_output_path), output); } while (1) { @@ -166,63 +166,63 @@ int main(int argc, char *argv[]) break; switch (i) { case 'r': - relative = true; + arg_relative = true; break; case 'f': - r = safe_atod(optarg, &hz); + r = safe_atod(optarg, &arg_hz); if (r < 0) log_warning("failed to parse --freq/-f argument '%s': %s", optarg, strerror(-r)); break; case 'F': - filter = false; + arg_filter = false; break; case 'C': - show_cmdline = true; + arg_show_cmdline = true; break; case 'n': - r = safe_atoi(optarg, &samples_len); + r = safe_atoi(optarg, &arg_samples_len); if (r < 0) log_warning("failed to parse --samples/-n argument '%s': %s", optarg, strerror(-r)); break; case 'o': path_kill_slashes(optarg); - strscpy(output_path, sizeof(output_path), optarg); + strscpy(arg_output_path, sizeof(arg_output_path), optarg); break; case 'i': path_kill_slashes(optarg); - strscpy(init_path, sizeof(init_path), optarg); + strscpy(arg_init_path, sizeof(arg_init_path), optarg); break; case 'p': - pss = true; + arg_pss = true; break; case 'x': - r = safe_atod(optarg, &scale_x); + r = safe_atod(optarg, &arg_scale_x); if (r < 0) log_warning("failed to parse --scale-x/-x argument '%s': %s", optarg, strerror(-r)); break; case 'y': - r = safe_atod(optarg, &scale_y); + r = safe_atod(optarg, &arg_scale_y); if (r < 0) log_warning("failed to parse --scale-y/-y argument '%s': %s", optarg, strerror(-r)); break; case 'e': - entropy = true; + arg_entropy = true; break; case 'h': fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]); fprintf(stderr, " --rel, -r Record time relative to recording\n"); - fprintf(stderr, " --freq, -f f Sample frequency [%f]\n", hz); - fprintf(stderr, " --samples, -n N Stop sampling at [%d] samples\n", samples_len); - fprintf(stderr, " --scale-x, -x N Scale the graph horizontally [%f] \n", scale_x); - fprintf(stderr, " --scale-y, -y N Scale the graph vertically [%f] \n", scale_y); + fprintf(stderr, " --freq, -f f Sample frequency [%f]\n", arg_hz); + fprintf(stderr, " --samples, -n N Stop sampling at [%d] samples\n", arg_samples_len); + fprintf(stderr, " --scale-x, -x N Scale the graph horizontally [%f] \n", arg_scale_x); + fprintf(stderr, " --scale-y, -y N Scale the graph vertically [%f] \n", arg_scale_y); fprintf(stderr, " --pss, -p Enable PSS graph (CPU intensive)\n"); fprintf(stderr, " --entropy, -e Enable the entropy_avail graph\n"); - fprintf(stderr, " --output, -o [PATH] Path to output files [%s]\n", output_path); - fprintf(stderr, " --init, -i [PATH] Path to init executable [%s]\n", init_path); + fprintf(stderr, " --output, -o [PATH] Path to output files [%s]\n", arg_output_path); + fprintf(stderr, " --init, -i [PATH] Path to init executable [%s]\n", arg_init_path); fprintf(stderr, " --no-filter, -F Disable filtering of processes from the graph\n"); fprintf(stderr, " that are of less importance or short-lived\n"); fprintf(stderr, " --cmdline, -C Display the full command line with arguments\n"); @@ -236,12 +236,12 @@ int main(int argc, char *argv[]) } } - if (samples_len > MAXSAMPLES) { + if (arg_samples_len > MAXSAMPLES) { fprintf(stderr, "Error: samples exceeds maximum\n"); exit(EXIT_FAILURE); } - if (hz <= 0.0) { + if (arg_hz <= 0.0) { fprintf(stderr, "Error: Frequency needs to be > 0\n"); exit(EXIT_FAILURE); } @@ -255,7 +255,7 @@ int main(int argc, char *argv[]) if (getpid() == 1) { if (fork()) { /* parent */ - execl(init_path, init_path, NULL); + execl(arg_init_path, arg_init_path, NULL); } } argv[0][0] = '@'; @@ -272,7 +272,7 @@ int main(int argc, char *argv[]) sig.sa_handler = signal_handler; sigaction(SIGHUP, &sig, NULL); - interval = (1.0 / hz) * 1000000000.0; + interval = (1.0 / arg_hz) * 1000000000.0; log_uptime(); @@ -288,22 +288,20 @@ int main(int argc, char *argv[]) sampletime[samples] = gettime_ns(); - if (!of && (access(output_path, R_OK|W_OK|X_OK) == 0)) { + if (!of && (access(arg_output_path, R_OK|W_OK|X_OK) == 0)) { t = time(NULL); strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t)); - snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", output_path, datestr); + snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", arg_output_path, datestr); of = fopen(output_file, "w"); } - if (sysfd < 0) { + if (sysfd < 0) sysfd = open("/sys", O_RDONLY); - } - if (!build) { + if (!build) parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &build, NULL); - } /* wait for /proc to become available, discarding samples */ if (!(graph_start > 0.0)) @@ -341,12 +339,12 @@ int main(int argc, char *argv[]) } else { overrun++; /* calculate how many samples we lost and scrap them */ - samples_len = samples_len + ((int)(newint_ns / interval)); + arg_samples_len = arg_samples_len + ((int)(newint_ns / interval)); } samples++; - if (samples > samples_len) + if (samples > arg_samples_len) break; } @@ -366,7 +364,7 @@ int main(int argc, char *argv[]) if (!of) { t = time(NULL); strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t)); - snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", output_path, datestr); + snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", arg_output_path, datestr); of = fopen(output_file, "w"); } @@ -378,10 +376,13 @@ int main(int argc, char *argv[]) svg_do(build); fprintf(stderr, "systemd-bootchart wrote %s\n", output_file); - fclose(of); + + if (of) + fclose(of); closedir(proc); - close(sysfd); + if (sysfd >= 0) + close(sysfd); /* nitpic cleanups */ ps = ps_first; diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h index 0fe4d2f4da..a9541caf4a 100644 --- a/src/bootchart/bootchart.h +++ b/src/bootchart/bootchart.h @@ -1,5 +1,9 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + /*** - bootchart.h - This file is part of systemd-bootchart + This file is part of systemd. Copyright (C) 2009-2013 Intel Coproration @@ -18,7 +22,7 @@ You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see <http://www.gnu.org/licenses/>. - ***/ +***/ #include <dirent.h> #include <stdbool.h> @@ -27,7 +31,6 @@ #define MAXPIDS 65535 #define MAXSAMPLES 8192 - struct block_stat_struct { /* /proc/vmstat pgpgin & pgpgout */ int bi; @@ -99,31 +102,23 @@ extern struct ps_struct *ps_first; extern struct block_stat_struct blockstat[]; extern struct cpu_stat_struct cpustat[]; extern int pscount; -extern bool relative; -extern bool filter; -extern bool show_cmdline; -extern bool pss; -extern bool entropy; +extern bool arg_relative; +extern bool arg_filter; +extern bool arg_show_cmdline; +extern bool arg_pss; +extern bool arg_entropy; extern bool initcall; extern int samples; extern int cpus; -extern int samples_len; -extern double hz; -extern double scale_x; -extern double scale_y; +extern int arg_samples_len; +extern double arg_hz; +extern double arg_scale_x; +extern double arg_scale_y; extern int overrun; extern double interval; -extern char output_path[PATH_MAX]; -extern char init_path[PATH_MAX]; +extern char arg_output_path[PATH_MAX]; +extern char arg_init_path[PATH_MAX]; extern FILE *of; -extern DIR *proc; -extern int procfd; extern int sysfd; - -extern double gettime_ns(void); -extern void log_uptime(void); -extern void log_sample(int sample); - -extern void svg_do(const char *build); diff --git a/src/bootchart/store.c b/src/bootchart/store.c index ccec03f12c..0253ebb5af 100644 --- a/src/bootchart/store.c +++ b/src/bootchart/store.c @@ -1,5 +1,7 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + /*** - log.c - This file is part of systemd-bootchart + This file is part of systemd. Copyright (C) 2009-2013 Intel Coproration @@ -20,7 +22,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#define _GNU_SOURCE 1 #include <unistd.h> #include <stdlib.h> #include <limits.h> @@ -32,9 +33,9 @@ #include <fcntl.h> #include <time.h> - -#include "bootchart.h" #include "util.h" +#include "store.h" +#include "bootchart.h" /* * Alloc a static 4k buffer for stdio - primarily used to increase @@ -43,10 +44,9 @@ */ static char smaps_buf[4096]; DIR *proc; -int procfd=-1; +int procfd = -1; -double gettime_ns(void) -{ +double gettime_ns(void) { struct timespec n; clock_gettime(CLOCK_MONOTONIC, &n); @@ -54,9 +54,7 @@ double gettime_ns(void) return (n.tv_sec + (n.tv_nsec / 1000000000.0)); } - -void log_uptime(void) -{ +void log_uptime(void) { FILE _cleanup_fclose_ *f = NULL; char str[32]; double uptime; @@ -73,15 +71,13 @@ void log_uptime(void) log_start = gettime_ns(); /* start graph at kernel boot time */ - if (relative) + if (arg_relative) graph_start = log_start; else graph_start = log_start - uptime; } - -static char *bufgetline(char *buf) -{ +static char *bufgetline(char *buf) { char *c; if (!buf) @@ -94,16 +90,16 @@ static char *bufgetline(char *buf) } static int pid_cmdline_strncpy(char *buffer, int pid, size_t buf_len) { - char filename[PATH_MAX]; - int _cleanup_close_ fd=-1; - ssize_t n; + char filename[PATH_MAX]; + int _cleanup_close_ fd=-1; + ssize_t n; - sprintf(filename, "%d/cmdline", pid); - fd = openat(procfd, filename, O_RDONLY); - if (fd < 0) - return -errno; + sprintf(filename, "%d/cmdline", pid); + fd = openat(procfd, filename, O_RDONLY); + if (fd < 0) + return -errno; - n = read(fd, buffer, buf_len-1); + n = read(fd, buffer, buf_len-1); if (n > 0) { int i; for (i = 0; i < n; i++) @@ -111,11 +107,10 @@ static int pid_cmdline_strncpy(char *buffer, int pid, size_t buf_len) { buffer[i] = ' '; buffer[n] = '\0'; } - return 0; + return 0; } -void log_sample(int sample) -{ +void log_sample(int sample) { static int vmstat; static int schedstat; char buf[4095]; @@ -214,7 +209,7 @@ schedstat_next: break; } - if (entropy) { + if (arg_entropy) { if (!e_fd) { e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY); } @@ -262,7 +257,7 @@ schedstat_next: ps = ps->next_ps; ps->pid = pid; - ps->sample = calloc(samples_len + 1, sizeof(struct ps_sched_struct)); + ps->sample = calloc(arg_samples_len + 1, sizeof(struct ps_sched_struct)); if (!ps->sample) { perror("calloc(ps_struct)"); exit (EXIT_FAILURE); @@ -294,7 +289,7 @@ schedstat_next: strncpy(ps->name, key, 256); /* cmdline */ - if (show_cmdline) + if (arg_show_cmdline) pid_cmdline_strncpy(ps->name, pid, 256); /* discard line 2 */ @@ -395,7 +390,7 @@ schedstat_next: - ps->sample[ps->first].runtime) / 1000000000.0; - if (!pss) + if (!arg_pss) goto catch_rename; /* Pss */ if (!ps->smaps) { @@ -428,7 +423,7 @@ schedstat_next: catch_rename: /* catch process rename, try to randomize time */ - mod = (hz < 4.0) ? 4.0 : (hz / 4.0); + mod = (arg_hz < 4.0) ? 4.0 : (arg_hz / 4.0); if (((samples - ps->first) + pid) % (int)(mod) == 0) { /* re-fetch name */ @@ -457,7 +452,7 @@ catch_rename: strncpy(ps->name, key, 256); /* cmdline */ - if (show_cmdline) + if (arg_show_cmdline) pid_cmdline_strncpy(ps->name, pid, 256); } } diff --git a/src/bootchart/store.h b/src/bootchart/store.h new file mode 100644 index 0000000000..e8d013cde4 --- /dev/null +++ b/src/bootchart/store.h @@ -0,0 +1,34 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright (C) 2009-2013 Intel Coproration + + Authors: + Auke Kok <auke-jan.h.kok@intel.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <dirent.h> + +extern DIR *proc; +extern int procfd; + +double gettime_ns(void); +void log_uptime(void); +void log_sample(int sample); diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index 9fee810795..231d3daa80 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -1,5 +1,7 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + /*** - bootchart.c - This file is part of systemd-bootchart + This file is part of systemd. Copyright (C) 2009-2013 Intel Coproration @@ -31,14 +33,15 @@ #include <sys/stat.h> #include <fcntl.h> -#include "bootchart.h" #include "util.h" #include "macro.h" +#include "store.h" +#include "svg.h" +#include "bootchart.h" - -#define time_to_graph(t) ((t) * scale_x) -#define ps_to_graph(n) ((n) * scale_y) -#define kb_to_graph(m) ((m) * scale_y * 0.0001) +#define time_to_graph(t) ((t) * arg_scale_x) +#define ps_to_graph(n) ((n) * arg_scale_y) +#define kb_to_graph(m) ((m) * arg_scale_y * 0.0001) #define to_color(n) (192.0 - ((n) * 192.0)) #define max(x, y) (((x) > (y)) ? (x) : (y)) @@ -48,7 +51,7 @@ static char str[8092]; #define svg(a...) do { snprintf(str, 8092, ## a); fputs(str, of); fflush(of); } while (0) -static const char *colorwheel[12] = { +static const char * const colorwheel[12] = { "rgb(255,32,32)", // red "rgb(32,192,192)", // cyan "rgb(255,128,32)", // orange @@ -71,9 +74,7 @@ static float psize = 0; static float ksize = 0; static float esize = 0; - -static void svg_header(void) -{ +static void svg_header(void) { float w; float h; @@ -82,8 +83,8 @@ static void svg_header(void) w = ((w < 1600.0) ? 1600.0 : w); /* height is variable based on pss, psize, ksize */ - h = 400.0 + (scale_y * 30.0) /* base graphs and title */ - + (pss ? (100.0 * scale_y) + (scale_y * 7.0) : 0.0) /* pss estimate */ + h = 400.0 + (arg_scale_y * 30.0) /* base graphs and title */ + + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */ + psize + ksize + esize; svg("<?xml version=\"1.0\" standalone=\"no\"?>\n"); @@ -103,11 +104,11 @@ static void svg_header(void) svg("<!-- your browser to file:///run/log/ and click. This bootchart was -->\n\n"); svg("<!-- generated by bootchart version %s, running with options: -->\n", VERSION); - svg("<!-- hz=\"%f\" n=\"%d\" -->\n", hz, samples_len); - svg("<!-- x=\"%f\" y=\"%f\" -->\n", scale_x, scale_y); - svg("<!-- rel=\"%d\" f=\"%d\" -->\n", relative, filter); - svg("<!-- p=\"%d\" e=\"%d\" -->\n", pss, entropy); - svg("<!-- o=\"%s\" i=\"%s\" -->\n\n", output_path, init_path); + svg("<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len); + svg("<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y); + svg("<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter); + svg("<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy); + svg("<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path); /* style sheet */ svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); @@ -136,12 +137,9 @@ static void svg_header(void) svg(" text.idle { font-size: 18; }\n"); svg(" ]]>\n </style>\n</defs>\n\n"); - } - -static void svg_title(const char *build) -{ +static void svg_title(const char *build) { char cmdline[256] = ""; char filename[PATH_MAX]; char buf[256]; @@ -222,12 +220,10 @@ static void svg_title(const char *build) svg("Not detected"); svg("</text>\n"); svg("<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n", - hz, samples_len, overrun, pscount, pfiltered); + arg_hz, arg_samples_len, overrun, pscount, pfiltered); } - -static void svg_graph_box(int height) -{ +static void svg_graph_box(int height) { double d = 0.0; int i = 0; @@ -238,7 +234,7 @@ static void svg_graph_box(int height) ps_to_graph(height)); for (d = graph_start; d <= sampletime[samples-1]; - d += (scale_x < 2.0 ? 60.0 : scale_x < 10.0 ? 1.0 : 0.1)) { + d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) { /* lines for each second */ if (i % 50 == 0) svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n", @@ -282,8 +278,7 @@ static char* xml_comment_encode(const char* name) { return enc_name; } -static void svg_pss_graph(void) -{ +static void svg_pss_graph(void) { struct ps_struct *ps; int i; @@ -320,7 +315,7 @@ static void svg_pss_graph(void) ps = ps->next_ps; if (!ps) continue; - if (ps->sample[i].pss <= (100 * scale_y)) + if (ps->sample[i].pss <= (100 * arg_scale_y)) top += ps->sample[i].pss; }; svg(" <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", @@ -339,7 +334,7 @@ static void svg_pss_graph(void) if (!ps) continue; /* don't draw anything smaller than 2mb */ - if (ps->sample[i].pss > (100 * scale_y)) { + if (ps->sample[i].pss > (100 * arg_scale_y)) { top = bottom + ps->sample[i].pss; svg(" <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", colorwheel[ps->pid % 12], @@ -366,7 +361,7 @@ static void svg_pss_graph(void) ps = ps->next_ps; if (!ps) continue; - if (ps->sample[i].pss <= (100 * scale_y)) + if (ps->sample[i].pss <= (100 * arg_scale_y)) top += ps->sample[i].pss; }; @@ -379,10 +374,10 @@ static void svg_pss_graph(void) if (!ps) continue; /* don't draw anything smaller than 2mb */ - if (ps->sample[i].pss > (100 * scale_y)) { + if (ps->sample[i].pss > (100 * arg_scale_y)) { top = bottom + ps->sample[i].pss; /* draw a label with the process / PID */ - if ((i == 1) || (ps->sample[i - 1].pss <= (100 * scale_y))) + if ((i == 1) || (ps->sample[i - 1].pss <= (100 * arg_scale_y))) svg(" <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n", time_to_graph(sampletime[i] - graph_start), kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)), @@ -416,8 +411,7 @@ static void svg_pss_graph(void) } -static void svg_io_bi_bar(void) -{ +static void svg_io_bi_bar(void) { double max = 0.0; double range; int max_here = 0; @@ -434,7 +428,7 @@ static void svg_io_bi_bar(void) * each poll. Applying a smoothing function loses some burst data, * so keep the smoothing range short. */ - range = 0.25 / (1.0 / hz); + range = 0.25 / (1.0 / arg_hz); if (range < 2.0) range = 2.0; /* no smoothing */ @@ -479,22 +473,21 @@ static void svg_io_bi_bar(void) if (pbi > 0.001) svg("<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", time_to_graph(sampletime[i - 1] - graph_start), - (scale_y * 5) - (pbi * (scale_y * 5)), + (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)), time_to_graph(sampletime[i] - sampletime[i - 1]), - pbi * (scale_y * 5)); + pbi * (arg_scale_y * 5)); /* labels around highest value */ if (i == max_here) { svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n", time_to_graph(sampletime[i] - graph_start) + 5, - ((scale_y * 5) - (pbi * (scale_y * 5))) + 15, + ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15, max / 1024.0 / (interval / 1000000000.0)); } } } -static void svg_io_bo_bar(void) -{ +static void svg_io_bo_bar(void) { double max = 0.0; double range; int max_here = 0; @@ -511,7 +504,7 @@ static void svg_io_bo_bar(void) * each poll. Applying a smoothing function loses some burst data, * so keep the smoothing range short. */ - range = 0.25 / (1.0 / hz); + range = 0.25 / (1.0 / arg_hz); if (range < 2.0) range = 2.0; /* no smoothing */ @@ -556,23 +549,21 @@ static void svg_io_bo_bar(void) if (pbo > 0.001) svg("<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", time_to_graph(sampletime[i - 1] - graph_start), - (scale_y * 5) - (pbo * (scale_y * 5)), + (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)), time_to_graph(sampletime[i] - sampletime[i - 1]), - pbo * (scale_y * 5)); + pbo * (arg_scale_y * 5)); /* labels around highest bo value */ if (i == max_here) { svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n", time_to_graph(sampletime[i] - graph_start) + 5, - ((scale_y * 5) - (pbo * (scale_y * 5))), + ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))), max / 1024.0 / (interval / 1000000000.0)); } } } - -static void svg_cpu_bar(void) -{ +static void svg_cpu_bar(void) { int i; svg("<!-- CPU utilization graph -->\n"); @@ -605,15 +596,14 @@ static void svg_cpu_bar(void) if (ptrt > 0.001) { svg("<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", time_to_graph(sampletime[i - 1] - graph_start), - (scale_y * 5) - (ptrt * (scale_y * 5)), + (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)), time_to_graph(sampletime[i] - sampletime[i - 1]), - ptrt * (scale_y * 5)); + ptrt * (arg_scale_y * 5)); } } } -static void svg_wait_bar(void) -{ +static void svg_wait_bar(void) { int i; svg("<!-- Wait time aggregation box -->\n"); @@ -647,16 +637,15 @@ static void svg_wait_bar(void) if (ptwt > 0.001) { svg("<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", time_to_graph(sampletime[i - 1] - graph_start), - ((scale_y * 5) - (ptwt * (scale_y * 5))), + ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))), time_to_graph(sampletime[i] - sampletime[i - 1]), - ptwt * (scale_y * 5)); + ptwt * (arg_scale_y * 5)); } } } -static void svg_entropy_bar(void) -{ +static void svg_entropy_bar(void) { int i; svg("<!-- entropy pool graph -->\n"); @@ -670,15 +659,13 @@ static void svg_entropy_bar(void) /* svg("<!-- entropy %.03f %i -->\n", sampletime[i], entropy_avail[i]); */ svg("<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", time_to_graph(sampletime[i - 1] - graph_start), - ((scale_y * 5) - ((entropy_avail[i] / 4096.) * (scale_y * 5))), + ((arg_scale_y * 5) - ((entropy_avail[i] / 4096.) * (arg_scale_y * 5))), time_to_graph(sampletime[i] - sampletime[i - 1]), - (entropy_avail[i] / 4096.) * (scale_y * 5)); + (entropy_avail[i] / 4096.) * (arg_scale_y * 5)); } } - -static struct ps_struct *get_next_ps(struct ps_struct *ps) -{ +static struct ps_struct *get_next_ps(struct ps_struct *ps) { /* * walk the list of processes and return the next one to be * painted @@ -707,10 +694,8 @@ static struct ps_struct *get_next_ps(struct ps_struct *ps) return NULL; } - -static int ps_filter(struct ps_struct *ps) -{ - if (!filter) +static int ps_filter(struct ps_struct *ps) { + if (!arg_filter) return 0; /* can't draw data when there is only 1 sample (need start + stop) */ @@ -728,9 +713,7 @@ static int ps_filter(struct ps_struct *ps) return 0; } - -static void svg_do_initcall(int count_only) -{ +static void svg_do_initcall(int count_only) { FILE _cleanup_pclose_ *f = NULL; double t; char func[256]; @@ -738,7 +721,7 @@ static void svg_do_initcall(int count_only) int usecs; /* can't plot initcall when disabled or in relative mode */ - if (!initcall || relative) { + if (!initcall || arg_relative) { kcount = 0; return; } @@ -818,9 +801,7 @@ static void svg_do_initcall(int count_only) } } - -static void svg_ps_bars(void) -{ +static void svg_ps_bars(void) { struct ps_struct *ps; int i = 0; int j = 0; @@ -966,7 +947,7 @@ static void svg_ps_bars(void) break; } - for (i = ps->first; i < samples - (hz / 2); i++) { + for (i = ps->first; i < samples - (arg_hz / 2); i++) { double crt; double brt; int c; @@ -974,8 +955,8 @@ static void svg_ps_bars(void) /* subtract bootchart cpu utilization from total */ crt = 0.0; for (c = 0; c < cpus; c++) - crt += cpustat[c].sample[i + ((int)hz / 2)].runtime - cpustat[c].sample[i].runtime; - brt = ps->sample[i + ((int)hz / 2)].runtime - ps->sample[i].runtime; + crt += cpustat[c].sample[i + ((int)arg_hz / 2)].runtime - cpustat[c].sample[i].runtime; + brt = ps->sample[i + ((int)arg_hz / 2)].runtime - ps->sample[i].runtime; /* * our definition of "idle": @@ -989,21 +970,19 @@ static void svg_ps_bars(void) idletime); svg("<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n", time_to_graph(idletime), - -scale_y, + -arg_scale_y, time_to_graph(idletime), - ps_to_graph(pcount) + scale_y); + ps_to_graph(pcount) + arg_scale_y); svg("<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n", time_to_graph(idletime) + 5.0, - ps_to_graph(pcount) + scale_y, + ps_to_graph(pcount) + arg_scale_y, idletime); break; } } } - -static void svg_top_ten_cpu(void) -{ +static void svg_top_ten_cpu(void) { struct ps_struct *top[10]; struct ps_struct emptyps; struct ps_struct *ps; @@ -1036,9 +1015,7 @@ static void svg_top_ten_cpu(void) top[n]->pid); } - -static void svg_top_ten_pss(void) -{ +static void svg_top_ten_pss(void) { struct ps_struct *top[10]; struct ps_struct emptyps; struct ps_struct *ps; @@ -1071,9 +1048,7 @@ static void svg_top_ten_pss(void) top[n]->pid); } - -void svg_do(const char *build) -{ +void svg_do(const char *build) { struct ps_struct *ps; memset(&str, 0, sizeof(str)); @@ -1082,7 +1057,7 @@ void svg_do(const char *build) /* count initcall thread count first */ svg_do_initcall(1); - ksize = (kcount ? ps_to_graph(kcount) + (scale_y * 2) : 0); + ksize = (kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0); /* then count processes */ while ((ps = get_next_ps(ps))) { @@ -1091,9 +1066,9 @@ void svg_do(const char *build) else pfiltered++; } - psize = ps_to_graph(pcount) + (scale_y * 2); + psize = ps_to_graph(pcount) + (arg_scale_y * 2); - esize = (entropy ? scale_y * 7 : 0); + esize = (arg_entropy ? arg_scale_y * 7 : 0); /* after this, we can draw the header with proper sizing */ svg_header(); @@ -1102,25 +1077,25 @@ void svg_do(const char *build) svg_io_bi_bar(); svg("</g>\n\n"); - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 7.0)); + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 7.0)); svg_io_bo_bar(); svg("</g>\n\n"); - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 14.0)); + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 14.0)); svg_cpu_bar(); svg("</g>\n\n"); - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 21.0)); + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 21.0)); svg_wait_bar(); svg("</g>\n\n"); if (kcount) { - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 28.0)); + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 28.0)); svg_do_initcall(0); svg("</g>\n\n"); } - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 28.0) + ksize); + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 28.0) + ksize); svg_ps_bars(); svg("</g>\n\n"); @@ -1132,14 +1107,14 @@ void svg_do(const char *build) svg_top_ten_cpu(); svg("</g>\n\n"); - if (entropy) { - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 28.0) + ksize + psize); + if (arg_entropy) { + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 28.0) + ksize + psize); svg_entropy_bar(); svg("</g>\n\n"); } - if (pss) { - svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 28.0) + ksize + psize + esize); + if (arg_pss) { + svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * 28.0) + ksize + psize + esize); svg_pss_graph(); svg("</g>\n\n"); diff --git a/src/bootchart/svg.h b/src/bootchart/svg.h new file mode 100644 index 0000000000..e7369f5111 --- /dev/null +++ b/src/bootchart/svg.h @@ -0,0 +1,27 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright (C) 2009-2013 Intel Coproration + + Authors: + Auke Kok <auke-jan.h.kok@intel.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +void svg_do(const char *build); |