svg.c revision 6bb25a058227d89fbbeba6c12873e6f83da5cf94
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering/***
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering bootchart.c - This file is part of systemd-bootchart
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Copyright (C) 2009-2013 Intel Coproration
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Authors:
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers Auke Kok <auke-jan.h.kok@intel.com>
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is free software; you can redistribute it and/or modify it
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering under the terms of the GNU Lesser General Public License as published by
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (at your option) any later version.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is distributed in the hope that it will be useful, but
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Lesser General Public License for more details.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering You should have received a copy of the GNU Lesser General Public License
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ***/
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include <stdio.h>
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include <stdarg.h>
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include <stdlib.h>
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner#include <string.h>
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include <time.h>
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen#include <limits.h>
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen#include <unistd.h>
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen#include <sys/utsname.h>
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include "bootchart.h"
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include "util.h"
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#include "macro.h"
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#define time_to_graph(t) ((t) * scale_x)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#define ps_to_graph(n) ((n) * scale_y)
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering#define kb_to_graph(m) ((m) * scale_y * 0.0001)
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace#define to_color(n) (192.0 - ((n) * 192.0))
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#define max(x, y) (((x) > (y)) ? (x) : (y))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#define min(x, y) (((x) < (y)) ? (x) : (y))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic char str[8092];
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering#define svg(a...) do { snprintf(str, 8092, ## a); fputs(str, of); fflush(of); } while (0)
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic const char *colorwheel[12] = {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(255,32,32)", // red
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(32,192,192)", // cyan
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(255,128,32)", // orange
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(128,32,192)", // blue-violet
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(255,255,32)", // yellow
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(192,32,128)", // red-violet
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(32,255,32)", // green
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering "rgb(255,64,32)", // red-orange
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering "rgb(32,32,255)", // blue
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering "rgb(255,192,32)", // yellow-orange
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(192,32,192)", // violet
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(32,192,32)" // yellow-green
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering};
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic double idletime = -1.0;
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sieversstatic int pfiltered = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic int pcount = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic int kcount = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic float psize = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic float ksize = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sieversstatic float esize = 0;
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void svg_header(void)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering{
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers float w;
f18ca9dcdeda247e208f7143e834fd2fb2070d80Kay Sievers float h;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* min width is about 1600px due to the label */
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden w = 150.0 + 10.0 + time_to_graph(sampletime[samples-1] - graph_start);
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering w = ((w < 1600.0) ? 1600.0 : w);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* height is variable based on pss, psize, ksize */
599659860c770058f2eb04d578c521c16e0b1853Lennart Poettering h = 400.0 + (scale_y * 30.0) /* base graphs and title */
599659860c770058f2eb04d578c521c16e0b1853Lennart Poettering + (pss ? (100.0 * scale_y) + (scale_y * 7.0) : 0.0) /* pss estimate */
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering + psize + ksize + esize;
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("<?xml version=\"1.0\" standalone=\"no\"?>\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
2311eb2ff0c3ff80ec3645b02c97170c9a565454Kay Sievers svg("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering //svg("<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ",
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering w, h);
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("xmlns=\"http://www.w3.org/2000/svg\">\n\n");
3e5e74d5b7f6fcbeff7b6e4e06abd931aab14c48Shawn Landden
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden /* write some basic info as a comment, including some help */
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<!-- such as Chrome, Chromium, or Firefox. Other applications that -->\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("<!-- render these files properly but more slowly are ImageMagick, gimp, -->\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<!-- inkscape, etc. To display the files on your system, just point -->\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<!-- your browser to file:///var/log/ and click. This bootchart was -->\n\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg("<!-- generated by bootchart version %s, running with options: -->\n", VERSION);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<!-- hz=\"%f\" n=\"%d\" -->\n", hz, len);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<!-- x=\"%f\" y=\"%f\" -->\n", scale_x, scale_y);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg("<!-- rel=\"%d\" f=\"%d\" -->\n", relative, filter);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg("<!-- p=\"%d\" e=\"%d\" -->\n", pss, entropy);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg("<!-- o=\"%s\" i=\"%s\" -->\n\n", output_path, init_path);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek /* style sheet */
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg(" rect { stroke-width: 1; }\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg(" rect.cpu { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" rect.wait { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers svg(" rect.bi { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers svg(" rect.bo { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" rect.ps { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" rect.krnl { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg(" rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg(" rect.clrw { stroke-width: 0; fill-opacity: 0.7;}\n");
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers svg(" line { stroke: rgb(64,64,64); stroke-width: 1; }\n");
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden svg("// line.sec1 { }\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" line.sec5 { stroke-width: 2; }\n");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg(" line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek svg(" line.dot { stroke-dasharray: 2 4; }\n");
2667cc25896a15f82f9f1583e80d416beb1316e1Thomas Hindoe Paaboel Andersen svg(" line.idle { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" .run { font-size: 8; font-style: italic; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" text { font-family: Verdana, Helvetica; font-size: 10; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" text.sec { font-size: 8; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" text.t1 { font-size: 24; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" text.t2 { font-size: 12; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" text.idle { font-size: 18; }\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering svg(" ]]>\n </style>\n</defs>\n\n");
d95a74ed1191bb09f5be57b0619d3d77708e019dLennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek}
2fc4f5bd924b9732afc70f8a6da80573f833fc9dLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void svg_title(void)
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek{
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers char cmdline[256] = "";
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers char filename[PATH_MAX];
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers char buf[256];
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering char rootbdev[16] = "Unknown";
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers char model[256] = "Unknown";
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering char date[256] = "Unknown";
c264aeab4b0e7b69f469e12e78d4a48b3ed7a66eKay Sievers char cpu[256] = "Unknown";
c264aeab4b0e7b69f469e12e78d4a48b3ed7a66eKay Sievers char build[256] = "Unknown";
c264aeab4b0e7b69f469e12e78d4a48b3ed7a66eKay Sievers char *c;
c264aeab4b0e7b69f469e12e78d4a48b3ed7a66eKay Sievers FILE *f;
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John time_t t;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering struct utsname uts;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* grab /proc/cmdline */
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek f = fopen("/proc/cmdline", "r");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (f) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!fgets(cmdline, 255, f))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers sprintf(cmdline, "Unknown");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers fclose(f);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* extract root fs so we can find disk model name in sysfs */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c = strstr(cmdline, "root=/dev/");
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (c) {
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers strncpy(rootbdev, &c[10], 3);
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers rootbdev[3] = '\0';
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen sprintf(filename, "/sys/block/%s/device/model", rootbdev);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering f = fopen(filename, "r");
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (f) {
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (!fgets(model, 255, f))
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers fprintf(stderr, "Error reading disk model for %s\n", rootbdev);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers fclose(f);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt /* various utsname parameters */
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (uname(&uts))
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering fprintf(stderr, "Error getting uname info\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* date */
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers t = time(NULL);
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers /* CPU type */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering f = fopen("/proc/cpuinfo", "r");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (f) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen while (fgets(buf, 255, f)) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (strstr(buf, "model name")) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen strncpy(cpu, &buf[13], 255);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering break;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering fclose(f);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Build - 1st line from /etc/system-release */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering f = fopen("/etc/system-release", "r");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (f) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (fgets(buf, 255, f))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering strncpy(build, buf, 255);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering fclose(f);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen uts.nodename, date);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen uts.sysname, uts.release, uts.version, uts.machine);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen cpu);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen model);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen cmdline);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen build);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (idletime >= 0.0)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("%.03fs", idletime);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering else
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("Not detected");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("</text>\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering 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",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering hz, len, overrun, pscount, pfiltered);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering}
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic void svg_graph_box(int height)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen{
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen double d = 0.0;
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen int i = 0;
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering /* outside box, fill */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John time_to_graph(0.0),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(sampletime[samples-1] - graph_start),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen ps_to_graph(height));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (d = graph_start; d <= sampletime[samples-1];
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen d += (scale_x < 2.0 ? 60.0 : scale_x < 10.0 ? 1.0 : 0.1)) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* lines for each second */
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering if (i % 50 == 0)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(d - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(d - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ps_to_graph(height));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering else if (i % 10 == 0)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering time_to_graph(d - graph_start),
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering time_to_graph(d - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ps_to_graph(height));
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering else
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(d - graph_start),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(d - graph_start),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen ps_to_graph(height));
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* time label */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (i % 10 == 0)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(d - graph_start),
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering -5.0,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen d - graph_start);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen i++;
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering}
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic void svg_pss_graph(void)
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering{
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering struct ps_struct *ps;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int i;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("\n\n<!-- Pss memory size graph -->\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("\n <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering /* vsize 1000 == 1000mb */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg_graph_box(100);
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering /* draw some hlines for usable memory sizes */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (i = 100000; i < 1000000; i += 100000) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(.0),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen kb_to_graph(i),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(sampletime[samples-1] - graph_start),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen kb_to_graph(i));
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen time_to_graph(sampletime[samples-1] - graph_start) + 5,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen kb_to_graph(i), (1000000 - i) / 1000);
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering }
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg("\n");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen /* now plot the graph itself */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen for (i = 1; i < samples ; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int bottom;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int top;
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering bottom = 0;
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering top = 0;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* put all the small pss blocks into the bottom */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ps = ps_first;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering while (ps->next_ps) {
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering ps = ps->next_ps;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (!ps)
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt continue;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (ps->sample[i].pss <= (100 * scale_y))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering top += ps->sample[i].pss;
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen };
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "rgb(64,64,64)",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i - 1] - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering kb_to_graph(1000000.0 - top),
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek time_to_graph(sampletime[i] - sampletime[i - 1]),
7591abd48079edc1f2adbd922e4b83eb73abeabeLennart Poettering kb_to_graph(top - bottom));
7591abd48079edc1f2adbd922e4b83eb73abeabeLennart Poettering
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John bottom = top;
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek /* now plot the ones that are of significant size */
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek ps = ps_first;
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek while (ps->next_ps) {
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek ps = ps->next_ps;
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek if (!ps)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering continue;
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek /* don't draw anything smaller than 2mb */
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek if (ps->sample[i].pss > (100 * scale_y)) {
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John top = bottom + ps->sample[i].pss;
07a062a79374406e8f6b5a1e2f80c80baf031567Jason St. John svg(" <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek colorwheel[ps->pid % 12],
3906ab4adf0aa7b952e39100262a11acd55cd79bRonny Chevalier time_to_graph(sampletime[i - 1] - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering kb_to_graph(1000000.0 - top),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i] - sampletime[i - 1]),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering kb_to_graph(top - bottom));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering bottom = top;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
c978343015c787713651dff571acb5207367f5f2Lennart Poettering /* overlay all the text labels */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (i = 1; i < samples ; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int bottom;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int top;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
c978343015c787713651dff571acb5207367f5f2Lennart Poettering bottom = 0;
c978343015c787713651dff571acb5207367f5f2Lennart Poettering top = 0;
c978343015c787713651dff571acb5207367f5f2Lennart Poettering
c978343015c787713651dff571acb5207367f5f2Lennart Poettering /* put all the small pss blocks into the bottom */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen ps = ps_first;
c978343015c787713651dff571acb5207367f5f2Lennart Poettering while (ps->next_ps) {
c978343015c787713651dff571acb5207367f5f2Lennart Poettering ps = ps->next_ps;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering if (!ps)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering continue;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (ps->sample[i].pss <= (100 * scale_y))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering top += ps->sample[i].pss;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering };
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering bottom = top;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek /* now plot the ones that are of significant size */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ps = ps_first;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering while (ps->next_ps) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ps = ps->next_ps;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (!ps)
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek continue;
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek /* don't draw anything smaller than 2mb */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (ps->sample[i].pss > (100 * scale_y)) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering top = bottom + ps->sample[i].pss;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* draw a label with the process / PID */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if ((i == 1) || (ps->sample[i - 1].pss <= (100 * scale_y)))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <text x=\"%.03f\" y=\"%.03f\">%s [%i]</text>\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i] - graph_start),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen ps->name,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen ps->pid);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering bottom = top;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen }
de33fc625725d199629ed074d6278504deb23debLennart Poettering }
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* debug output - full data dump */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("\n\n<!-- PSS map - csv format -->\n");
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen ps = ps_first;
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen while (ps->next_ps) {
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen ps = ps->next_ps;
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen if (!ps)
c978343015c787713651dff571acb5207367f5f2Lennart Poettering continue;
c978343015c787713651dff571acb5207367f5f2Lennart Poettering svg("<!-- %s [%d] pss=", ps->name, ps->pid);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (i = 0; i < samples ; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("%d," , ps->sample[i].pss);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" -->\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering}
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void svg_io_bi_bar(void)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering{
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering double max = 0.0;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double range;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int max_here = 0;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int i;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<!-- IO utilization graph - In -->\n");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /*
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * calculate rounding range
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering *
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * We need to round IO data since IO block data is not updated on
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * each poll. Applying a smoothing function loses some burst data,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * so keep the smoothing range short.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen range = 0.25 / (1.0 / hz);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (range < 2.0)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering range = 2.0; /* no smoothing */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* surrounding box */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg_graph_box(5);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* find the max IO first */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (i = 1; i < samples; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int start;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int stop;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double tot;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering start = max(i - ((range / 2) - 1), 0);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering stop = min(i + (range / 2), samples - 1);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering tot = (double)(blockstat[stop].bi - blockstat[start].bi)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering / (stop - start);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (tot > max) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering max = tot;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering max_here = i;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering tot = (double)(blockstat[stop].bo - blockstat[start].bo)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering / (stop - start);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (tot > max)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering max = tot;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* plot bi */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering for (i = 1; i < samples; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int start;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int stop;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double tot;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double pbi;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering start = max(i - ((range / 2) - 1), 0);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering stop = min(i + (range / 2), samples);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering tot = (double)(blockstat[stop].bi - blockstat[start].bi)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering / (stop - start);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering pbi = tot / max;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (pbi > 0.001)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i - 1] - graph_start),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (scale_y * 5) - (pbi * (scale_y * 5)),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i] - sampletime[i - 1]),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering pbi * (scale_y * 5));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* labels around highest value */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (i == max_here) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering time_to_graph(sampletime[i] - graph_start) + 5,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering ((scale_y * 5) - (pbi * (scale_y * 5))) + 15,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering max / 1024.0 / (interval / 1000000000.0));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering }
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering}
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void svg_io_bo_bar(void)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering{
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double max = 0.0;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering double range;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int max_here = 0;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int i;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<!-- IO utilization graph - out -->\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering svg("<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /*
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering * calculate rounding range
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering *
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * We need to round IO data since IO block data is not updated on
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner * each poll. Applying a smoothing function loses some burst data,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * so keep the smoothing range short.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering range = 0.25 / (1.0 / hz);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (range < 2.0)
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering range = 2.0; /* no smoothing */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* surrounding box */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen svg_graph_box(5);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt /* find the max IO first */
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen for (i = 1; i < samples; i++) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int start;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering int stop;
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen double tot;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen start = max(i - ((range / 2) - 1), 0);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering stop = min(i + (range / 2), samples - 1);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering tot = (double)(blockstat[stop].bi - blockstat[start].bi)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering / (stop - start);
if (tot > max)
max = tot;
tot = (double)(blockstat[stop].bo - blockstat[start].bo)
/ (stop - start);
if (tot > max) {
max = tot;
max_here = i;
}
}
/* plot bo */
for (i = 1; i < samples; i++) {
int start;
int stop;
double tot;
double pbo;
start = max(i - ((range / 2) - 1), 0);
stop = min(i + (range / 2), samples);
tot = (double)(blockstat[stop].bo - blockstat[start].bo)
/ (stop - start);
pbo = tot / max;
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)),
time_to_graph(sampletime[i] - sampletime[i - 1]),
pbo * (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))),
max / 1024.0 / (interval / 1000000000.0));
}
}
}
static void svg_cpu_bar(void)
{
int i;
svg("<!-- CPU utilization graph -->\n");
svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU utilization</text>\n");
/* surrounding box */
svg_graph_box(5);
/* bars for each sample, proportional to the CPU util. */
for (i = 1; i < samples; i++) {
int c;
double trt;
double ptrt;
ptrt = trt = 0.0;
for (c = 0; c < cpus; c++)
trt += cpustat[c].sample[i].runtime - cpustat[c].sample[i - 1].runtime;
trt = trt / 1000000000.0;
trt = trt / (double)cpus;
if (trt > 0.0)
ptrt = trt / (sampletime[i] - sampletime[i - 1]);
if (ptrt > 1.0)
ptrt = 1.0;
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)),
time_to_graph(sampletime[i] - sampletime[i - 1]),
ptrt * (scale_y * 5));
}
}
}
static void svg_wait_bar(void)
{
int i;
svg("<!-- Wait time aggregation box -->\n");
svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU wait</text>\n");
/* surrounding box */
svg_graph_box(5);
/* bars for each sample, proportional to the CPU util. */
for (i = 1; i < samples; i++) {
int c;
double twt;
double ptwt;
ptwt = twt = 0.0;
for (c = 0; c < cpus; c++)
twt += cpustat[c].sample[i].waittime - cpustat[c].sample[i - 1].waittime;
twt = twt / 1000000000.0;
twt = twt / (double)cpus;
if (twt > 0.0)
ptwt = twt / (sampletime[i] - sampletime[i - 1]);
if (ptwt > 1.0)
ptwt = 1.0;
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))),
time_to_graph(sampletime[i] - sampletime[i - 1]),
ptwt * (scale_y * 5));
}
}
}
static void svg_entropy_bar(void)
{
int i;
svg("<!-- entropy pool graph -->\n");
svg("<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
/* surrounding box */
svg_graph_box(5);
/* bars for each sample, scale 0-4096 */
for (i = 1; i < samples; i++) {
/* 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))),
time_to_graph(sampletime[i] - sampletime[i - 1]),
(entropy_avail[i] / 4096.) * (scale_y * 5));
}
}
static struct ps_struct *get_next_ps(struct ps_struct *ps)
{
/*
* walk the list of processes and return the next one to be
* painted
*/
if (ps == ps_first)
return ps->next_ps;
/* go deep */
if (ps->children)
return ps->children;
/* find siblings */
if (ps->next)
return ps->next;
/* go back for parent siblings */
while (1) {
if (ps->parent)
if (ps->parent->next)
return ps->parent->next;
ps = ps->parent;
if (!ps)
return ps;
}
return NULL;
}
static int ps_filter(struct ps_struct *ps)
{
if (!filter)
return 0;
/* can't draw data when there is only 1 sample (need start + stop) */
if (ps->first == ps->last)
return -1;
/* don't filter kthreadd */
if (ps->pid == 2)
return 0;
/* drop stuff that doesn't use any real CPU time */
if (ps->total <= 0.001)
return -1;
return 0;
}
static void svg_do_initcall(int count_only)
{
FILE _cleanup_pclose_ *f = NULL;
double t;
char func[256];
int ret;
int usecs;
/* can't plot initcall when disabled or in relative mode */
if (!initcall || relative) {
kcount = 0;
return;
}
if (!count_only) {
svg("<!-- initcall -->\n");
svg("<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
/* surrounding box */
svg_graph_box(kcount);
}
kcount = 0;
/*
* Initcall graphing - parses dmesg buffer and displays kernel threads
* This somewhat uses the same methods and scaling to show processes
* but looks a lot simpler. It's overlaid entirely onto the PS graph
* when appropriate.
*/
f = popen("dmesg", "r");
if (!f)
return;
while (!feof(f)) {
int c;
int z = 0;
char l[256];
if (fgets(l, sizeof(l) - 1, f) == NULL)
continue;
c = sscanf(l, "[%lf] initcall %s %*s %d %*s %d %*s",
&t, func, &ret, &usecs);
if (c != 4) {
/* also parse initcalls done by module loading */
c = sscanf(l, "[%lf] initcall %s %*s %*s %d %*s %d %*s",
&t, func, &ret, &usecs);
if (c != 4)
continue;
}
/* chop the +0xXX/0xXX stuff */
while(func[z] != '+')
z++;
func[z] = 0;
if (count_only) {
/* filter out irrelevant stuff */
if (usecs >= 1000)
kcount++;
continue;
}
svg("<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
func, t, usecs, ret);
if (usecs < 1000)
continue;
/* rect */
svg(" <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
time_to_graph(t - (usecs / 1000000.0)),
ps_to_graph(kcount),
time_to_graph(usecs / 1000000.0),
ps_to_graph(1));
/* label */
svg(" <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
time_to_graph(t - (usecs / 1000000.0)) + 5,
ps_to_graph(kcount) + 15,
func,
usecs / 1000000.0);
kcount++;
}
}
static void svg_ps_bars(void)
{
struct ps_struct *ps;
int i = 0;
int j = 0;
int w;
int pid;
svg("<!-- Process graph -->\n");
svg("<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
/* surrounding box */
svg_graph_box(pcount);
/* pass 2 - ps boxes */
ps = ps_first;
while ((ps = get_next_ps(ps))) {
double starttime;
int t;
if (!ps)
continue;
/* leave some trace of what we actually filtered etc. */
svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", ps->name, ps->pid,
ps->ppid, ps->total);
/* it would be nice if we could use exec_start from /proc/pid/sched,
* but it's unreliable and gives bogus numbers */
starttime = sampletime[ps->first];
if (!ps_filter(ps)) {
/* remember where _to_ our children need to draw a line */
ps->pos_x = time_to_graph(starttime - graph_start);
ps->pos_y = ps_to_graph(j+1); /* bottom left corner */
} else {
/* hook children to our parent coords instead */
ps->pos_x = ps->parent->pos_x;
ps->pos_y = ps->parent->pos_y;
/* if this is the last child, we might still need to draw a connecting line */
if ((!ps->next) && (ps->parent))
svg(" <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
ps->parent->pos_x,
ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
ps->parent->pos_x,
ps->parent->pos_y);
continue;
}
svg(" <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
time_to_graph(starttime - graph_start),
ps_to_graph(j),
time_to_graph(sampletime[ps->last] - starttime),
ps_to_graph(1));
/* paint cpu load over these */
for (t = ps->first + 1; t < ps->last; t++) {
double rt, prt;
double wt, wrt;
/* calculate over interval */
rt = ps->sample[t].runtime - ps->sample[t-1].runtime;
wt = ps->sample[t].waittime - ps->sample[t-1].waittime;
prt = (rt / 1000000000) / (sampletime[t] - sampletime[t-1]);
wrt = (wt / 1000000000) / (sampletime[t] - sampletime[t-1]);
/* this can happen if timekeeping isn't accurate enough */
if (prt > 1.0)
prt = 1.0;
if (wrt > 1.0)
wrt = 1.0;
if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */
continue;
svg(" <rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
time_to_graph(sampletime[t - 1] - graph_start),
ps_to_graph(j),
time_to_graph(sampletime[t] - sampletime[t - 1]),
ps_to_graph(wrt));
/* draw cpu over wait - TODO figure out how/why run + wait > interval */
svg(" <rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
time_to_graph(sampletime[t - 1] - graph_start),
ps_to_graph(j + (1.0 - prt)),
time_to_graph(sampletime[t] - sampletime[t - 1]),
ps_to_graph(prt));
}
/* determine where to display the process name */
if (sampletime[ps->last] - sampletime[ps->first] < 1.5)
/* too small to fit label inside the box */
w = ps->last;
else
w = ps->first;
/* text label of process name */
svg(" <text x=\"%.03f\" y=\"%.03f\">%s [%i] <tspan class=\"run\">%.03fs</tspan></text>\n",
time_to_graph(sampletime[w] - graph_start) + 5.0,
ps_to_graph(j) + 14.0,
ps->name,
ps->pid,
(ps->sample[ps->last].runtime - ps->sample[ps->first].runtime) / 1000000000.0);
/* paint lines to the parent process */
if (ps->parent) {
/* horizontal part */
svg(" <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
time_to_graph(starttime - graph_start),
ps_to_graph(j) + 10.0,
ps->parent->pos_x,
ps_to_graph(j) + 10.0);
/* one vertical line connecting all the horizontal ones up */
if (!ps->next)
svg(" <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
ps->parent->pos_x,
ps_to_graph(j) + 10.0,
ps->parent->pos_x,
ps->parent->pos_y);
}
j++; /* count boxes */
svg("\n");
}
/* last pass - determine when idle */
pid = getpid();
/* make sure we start counting from the point where we actually have
* data: assume that bootchart's first sample is when data started
*/
ps = ps_first;
while (ps->next_ps) {
ps = ps->next_ps;
if (ps->pid == pid)
break;
}
for (i = ps->first; i < samples - (hz / 2); i++) {
double crt;
double brt;
int c;
/* 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;
/*
* our definition of "idle":
*
* if for (hz / 2) we've used less CPU than (interval / 2) ...
* defaults to 4.0%, which experimentally, is where atom idles
*/
if ((crt - brt) < (interval / 2.0)) {
idletime = sampletime[i] - graph_start;
svg("\n<!-- idle detected at %.03f seconds -->\n",
idletime);
svg("<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
time_to_graph(idletime),
-scale_y,
time_to_graph(idletime),
ps_to_graph(pcount) + 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,
idletime);
break;
}
}
}
static void svg_top_ten_cpu(void)
{
struct ps_struct *top[10];
struct ps_struct emptyps;
struct ps_struct *ps;
int n, m;
memset(&emptyps, 0, sizeof(struct ps_struct));
for (n=0; n < 10; n++)
top[n] = &emptyps;
/* walk all ps's and setup ptrs */
ps = ps_first;
while ((ps = get_next_ps(ps))) {
for (n = 0; n < 10; n++) {
if (ps->total <= top[n]->total)
continue;
/* cascade insert */
for (m = 9; m > n; m--)
top[m] = top[m-1];
top[n] = ps;
break;
}
}
svg("<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
for (n = 0; n < 10; n++)
svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - %s[%d]</text>\n",
20 + (n * 13),
top[n]->total,
top[n]->name,
top[n]->pid);
}
static void svg_top_ten_pss(void)
{
struct ps_struct *top[10];
struct ps_struct emptyps;
struct ps_struct *ps;
int n, m;
memset(&emptyps, 0, sizeof(struct ps_struct));
for (n=0; n < 10; n++)
top[n] = &emptyps;
/* walk all ps's and setup ptrs */
ps = ps_first;
while ((ps = get_next_ps(ps))) {
for (n = 0; n < 10; n++) {
if (ps->pss_max <= top[n]->pss_max)
continue;
/* cascade insert */
for (m = 9; m > n; m--)
top[m] = top[m-1];
top[n] = ps;
break;
}
}
svg("<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
for (n = 0; n < 10; n++)
svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - %s[%d]</text>\n",
20 + (n * 13),
top[n]->pss_max,
top[n]->name,
top[n]->pid);
}
void svg_do(void)
{
struct ps_struct *ps;
memset(&str, 0, sizeof(str));
ps = ps_first;
/* count initcall thread count first */
svg_do_initcall(1);
ksize = (kcount ? ps_to_graph(kcount) + (scale_y * 2) : 0);
/* then count processes */
while ((ps = get_next_ps(ps))) {
if (!ps_filter(ps))
pcount++;
else
pfiltered++;
}
psize = ps_to_graph(pcount) + (scale_y * 2);
esize = (entropy ? scale_y * 7 : 0);
/* after this, we can draw the header with proper sizing */
svg_header();
svg("<g transform=\"translate(10,400)\">\n");
svg_io_bi_bar();
svg("</g>\n\n");
svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (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_cpu_bar();
svg("</g>\n\n");
svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (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_do_initcall(0);
svg("</g>\n\n");
}
svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (scale_y * 28.0) + ksize);
svg_ps_bars();
svg("</g>\n\n");
svg("<g transform=\"translate(10, 0)\">\n");
svg_title();
svg("</g>\n\n");
svg("<g transform=\"translate(10,200)\">\n");
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);
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);
svg_pss_graph();
svg("</g>\n\n");
svg("<g transform=\"translate(410,200)\">\n");
svg_top_ten_pss();
svg("</g>\n\n");
}
/* svg footer */
svg("\n</svg>\n");
}