svg.c revision f2d28e80bc6260c90396e9fc798d559775dbde23
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/***
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen This file is part of systemd.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Copyright (C) 2009-2013 Intel Corporation
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Authors:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Auke Kok <auke-jan.h.kok@intel.com>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is free software; you can redistribute it and/or modify it
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen under the terms of the GNU Lesser General Public License as published by
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (at your option) any later version.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is distributed in the hope that it will be useful, but
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Lesser General Public License for more details.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen You should have received a copy of the GNU Lesser General Public License
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ***/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <stdio.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <string.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <time.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <limits.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <unistd.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <sys/utsname.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <fcntl.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "architecture.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "util.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "fileio.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "macro.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "store.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "svg.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "bootchart.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "list.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "utf8.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#define time_to_graph(t) ((t) * arg_scale_x)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#define ps_to_graph(n) ((n) * arg_scale_y)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#define kb_to_graph(m) ((m) * arg_scale_y * 0.0001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#define to_color(n) (192.0 - ((n) * 192.0))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic const char * const colorwheel[12] = {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(255,32,32)", // red
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(32,192,192)", // cyan
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(255,128,32)", // orange
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(128,32,192)", // blue-violet
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(255,255,32)", // yellow
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(192,32,128)", // red-violet
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(32,255,32)", // green
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(255,64,32)", // red-orange
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(32,32,255)", // blue
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(255,192,32)", // yellow-orange
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(192,32,192)", // violet
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(32,192,32)" // yellow-green
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen};
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic double idletime = -1.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int pfiltered = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int pcount = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int kcount = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic double psize = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic double ksize = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic double esize = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic struct list_sample_data *sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic struct list_sample_data *prev_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_header(FILE *of, struct list_sample_data *head, double graph_start, int n_cpus) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double w;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double h;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *sampledata_last;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(head);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* min width is about 1600px due to the label */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen w = 150.0 + 10.0 + time_to_graph(sampledata_last->sampletime - graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen w = ((w < 1600.0) ? 1600.0 : w);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* height is variable based on pss, psize, ksize */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen h = 400.0 + (arg_scale_y * 30.0) /* base graphs and title */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen + psize + ksize + esize + (n_cpus * 15 * arg_scale_y);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen //fprintf(of, "<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ", w, h);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "xmlns=\"http://www.w3.org/2000/svg\">\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* write some basic info as a comment, including some help */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- such as Chrome, Chromium, or Firefox. Other applications that -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- render these files properly but more slowly are ImageMagick, gimp, -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- inkscape, etc. To display the files on your system, just point -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- your browser to file:///run/log/ and click. This bootchart was -->\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- generated by bootchart version %s, running with options: -->\n", VERSION);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* style sheet */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect { stroke-width: 1; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.bg { fill: rgb(255,255,255); }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.cpu { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.wait { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.bi { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.bo { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.ps { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.krnl { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " rect.clrw { stroke-width: 0; fill-opacity: 0.7;}\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " line { stroke: rgb(64,64,64); stroke-width: 1; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "// line.sec1 { }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " line.sec5 { stroke-width: 2; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " line.dot { stroke-dasharray: 2 4; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " line.idle { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " .run { font-size: 8; font-style: italic; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " text { font-family: Verdana, Helvetica; font-size: 10; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " text.sec { font-size: 8; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " text.t1 { font-size: 24; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " text.t2 { font-size: 12; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " text.idle { font-size: 18; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " ]]>\n </style>\n</defs>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *cmdline = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *model = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *buf = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char date[256] = "Unknown";
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *cpu;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char *c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_t t;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct utsname uts;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = read_one_line_file("/proc/cmdline", &cmdline);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error_errno(r, "Unable to read cmdline: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen }
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen /* extract root fs so we can find disk model name in sysfs */
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen /* FIXME: this works only in the simple case */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen c = strstr(cmdline, "root=/dev/");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (c) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char rootbdev[4];
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen char filename[32];
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen rootbdev[3] = '\0';
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = read_one_line_file(filename, &model);
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_info("Error reading disk model for %s: %m\n", rootbdev);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* various utsname parameters */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = uname(&uts);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Error getting uname info\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -errno;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* date */
52d629010db73a9466c359201916494bd55186d1Tom Gundersen t = time(NULL);
52d629010db73a9466c359201916494bd55186d1Tom Gundersen r = strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
52d629010db73a9466c359201916494bd55186d1Tom Gundersen assert_se(r > 0);
52d629010db73a9466c359201916494bd55186d1Tom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* CPU type */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen cpu = "Unknown";
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
52d629010db73a9466c359201916494bd55186d1Tom Gundersen cpu = buf;
52d629010db73a9466c359201916494bd55186d1Tom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen uts.nodename, date);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen uts.sysname, uts.release, uts.version, uts.machine);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (model)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (idletime >= 0.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "%.03fs", idletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "Not detected");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen arg_hz, arg_samples_len, overrun, pscount, pfiltered);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_graph_box(FILE *of, struct list_sample_data *head, int height, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double d = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int i = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double finalsample = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *sampledata_last;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen finalsample = sampledata_last->sampletime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* outside box, fill */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(0.0),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(finalsample - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(height));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (d = graph_start; d <= finalsample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* lines for each second */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (i % 50 == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(height));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else if (i % 10 == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(height));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(height));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* time label */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (i % 10 == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(d - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen -5.0, d - graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/* xml comments must not contain "--" */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic char* xml_comment_encode(const char* name) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char *enc_name, *p;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen enc_name = strdup(name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!enc_name)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (p = enc_name; *p; p++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (p[0] == '-' && p[1] == '-')
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen p[1] = '_';
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return enc_name;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_pss_graph(FILE *of,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *head,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps_first,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *sampledata_last;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata_last = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n\n<!-- Pss memory size graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* vsize 1000 == 1000mb */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 100, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* draw some hlines for usable memory sizes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (i = 100000; i < 1000000; i += 100000) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(.0),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(i),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata_last->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(i));
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata_last->sampletime - graph_start) + 5,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(i), (1000000 - i) / 1000);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* now plot the graph itself */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int bottom;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_sched_struct *cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* put all the small pss blocks into the bottom */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss <= (100 * arg_scale_y))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top += ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->cross) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen cross_place = ps->sample->cross;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->sample->cross->ps_new;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss <= (100 * arg_scale_y))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top += ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "rgb(64,64,64)",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(1000000.0 - top),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(top - bottom));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* now plot the ones that are of significant size */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't draw anything smaller than 2mb */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata != sampledata)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss > (100 * arg_scale_y)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top = bottom + ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen colorwheel[ps->pid % 12],
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(1000000.0 - top),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(top - bottom));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((cross_place = ps->sample->cross)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->sample->cross->ps_new;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss > (100 * arg_scale_y)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top = bottom + ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen colorwheel[ps->pid % 12],
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(1000000.0 - top),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(top - bottom));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* overlay all the text labels */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int bottom;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int top = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_sched_struct *prev_sample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_sched_struct *cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* put all the small pss blocks into the bottom */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss <= (100 * arg_scale_y))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top += ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((cross_place = ps->sample->cross)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->sample->cross->ps_new;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss <= (100 * arg_scale_y))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top += ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* now plot the ones that are of significant size */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sample = ps->sample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sample = ps->sample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't draw anything smaller than 2mb */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->sampledata == sampledata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss > (100 * arg_scale_y)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top = bottom + ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* draw a label with the process / PID */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->name, ps->pid);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((cross_place = ps->sample->cross)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->sample->cross->ps_new;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = cross_place;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sample = ps->sample->prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->sample->pss > (100 * arg_scale_y)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top = bottom + ps->sample->pss;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* draw a label with the process / PID */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->name, ps->pid);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen bottom = top;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* debug output - full data dump */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n\n<!-- PSS map - csv format -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *enc_name = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
7141e4f62c3f220872df3114c42d9e4b9525e43eTom Gundersen continue;
7141e4f62c3f220872df3114c42d9e4b9525e43eTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen enc_name = xml_comment_encode(ps->name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!enc_name)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- %s [%d] pss=", enc_name, ps->pid);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
bba061662b0f759abb43bad60c9733305c191045Tom Gundersen while (ps->sample->next) {
bba061662b0f759abb43bad60c9733305c191045Tom Gundersen ps->sample = ps->sample->next;
bba061662b0f759abb43bad60c9733305c191045Tom Gundersen fprintf(of, "%d," , ps->sample->pss);
2a2137401b3aef20618308d2b2694e21b0124f89Tom Gundersen }
2a2137401b3aef20618308d2b2694e21b0124f89Tom Gundersen
2a2137401b3aef20618308d2b2694e21b0124f89Tom Gundersen fprintf(of, " -->\n");
bba061662b0f759abb43bad60c9733305c191045Tom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_io_bi_bar(FILE *of,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *head,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_samples,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double graph_start,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double interval) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double max = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double range;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int max_here = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int k;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *start_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *stop_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- IO utilization graph - In -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /*
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * calculate rounding range
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen *
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * We need to round IO data since IO block data is not updated on
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * each poll. Applying a smoothing function loses some burst data,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * so keep the smoothing range short.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen range = 0.25 / (1.0 / arg_hz);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (range < 2.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen range = 2.0; /* no smoothing */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 5, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find the max IO first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int start;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int stop;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start = MAX(i - ((range / 2) - 1), 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop = MIN(i + (range / 2), n_samples - 1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen diff = (stop - start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = stop_sampledata->link_prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (tot > max) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max = tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max_here = i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (tot > max)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max = tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* plot bi */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int start;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int stop;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double pbi = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start = MAX(i - ((range / 2) - 1), 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop = MIN(i + (range / 2), n_samples);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen diff = (stop - start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = stop_sampledata->link_prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (max > 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pbi = tot / max;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (pbi > 0.001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pbi * (arg_scale_y * 5));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* labels around highest value */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (i == max_here)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - graph_start) + 5,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max / 1024.0 / (interval / 1000000000.0));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_io_bo_bar(FILE *of,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *head,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_samples,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double graph_start,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double interval) {
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen double max = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double range;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int max_here = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int k;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *start_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *stop_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- IO utilization graph - out -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /*
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * calculate rounding range
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen *
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * We need to round IO data since IO block data is not updated on
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * each poll. Applying a smoothing function loses some burst data,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * so keep the smoothing range short.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen range = 0.25 / (1.0 / arg_hz);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (range < 2.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen range = 2.0; /* no smoothing */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 5, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find the max IO first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int start;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int stop;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start = MAX(i - ((range / 2) - 1), 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop = MIN(i + (range / 2), n_samples - 1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen diff = (stop - start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = stop_sampledata->link_prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (tot > max)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max = tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (tot > max) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max = tot;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max_here = i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* plot bo */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int start, stop, diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double tot, pbo;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pbo = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start = MAX(i - ((range / 2) - 1), 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop = MIN(i + (range / 2), n_samples);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen diff = (stop - start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen start_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen stop_sampledata = stop_sampledata->link_prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (max > 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pbo = tot / max;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (pbo > 0.001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pbo * (arg_scale_y * 5));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* labels around highest bo value */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (i == max_here)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - graph_start) + 5,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen max / 1024.0 / (interval / 1000000000.0));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- CPU utilization graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 5, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, proportional to the CPU util. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double trt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double ptrt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptrt = trt = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt += sampledata->runtime[c] - prev_sampledata->runtime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt = trt / 1000000000.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt = trt / (double)n_cpus;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (trt > 0.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ptrt > 1.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptrt = 1.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
85091685af65831f379580c75b40776c20e245eeTom Gundersen if (ptrt > 0.001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
5a917c064b23c1b8a12d6abd2f9f31c575ddebc6Tom Gundersen (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptrt * (arg_scale_y * 5));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- Wait time aggregation box -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 5, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, proportional to the CPU util. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double twt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double ptwt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptwt = twt = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt += sampledata->waittime[c] - prev_sampledata->waittime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt = twt / 1000000000.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (cpu_num < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt = twt / (double)n_cpus;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (twt > 0.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ptwt > 1.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptwt = 1.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ptwt > 0.001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptwt * (arg_scale_y * 5));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_entropy_bar(FILE *of, struct list_sample_data *head, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- entropy pool graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, 5, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, scale 0-4096 */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FOREACH_BEFORE(link, sampledata, head) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ((arg_scale_y * 5) - ((sampledata->entropy_avail / 4096.) * (arg_scale_y * 5))),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (sampledata->entropy_avail / 4096.) * (arg_scale_y * 5));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev_sampledata = sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_first) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /*
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * walk the list of processes and return the next one to be
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * painted
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps == ps_first)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* go deep */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->children)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return ps->children;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find siblings */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->next)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return ps->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* go back for parent siblings */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (;;) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->parent && ps->parent->next)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return ps->parent->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->parent;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic bool ps_filter(struct ps_struct *ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!arg_filter)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return false;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* can't draw data when there is only 1 sample (need start + stop) */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->first == ps->last)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return true;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't filter kthreadd */
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen if (ps->pid == 2)
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen return false;
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen /* drop stuff that doesn't use any real CPU time */
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen if (ps->total <= 0.001)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return true;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_pclose_ FILE *f = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double t;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char func[256];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int ret;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int usecs;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* can't plot initcall when disabled or in relative mode */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!arg_initcall || arg_relative) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kcount = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!count_only) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- initcall -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, kcount, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kcount = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /*
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * Initcall graphing - parses dmesg buffer and displays kernel threads
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * This somewhat uses the same methods and scaling to show processes
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * but looks a lot simpler. It's overlaid entirely onto the PS graph
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * when appropriate.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen f = popen("dmesg", "r");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!f)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (!feof(f)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int z = 0;
afcac065c0f649ebcf0f450475a8d7c3bc776d14Tom Gundersen char l[256];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (fgets(l, sizeof(l) - 1, f) == NULL)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen c = sscanf(l, "[%lf] initcall %s %*s %d %*s %d %*s",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen &t, func, &ret, &usecs);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (c != 4) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* also parse initcalls done by module loading */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen c = sscanf(l, "[%lf] initcall %s %*s %*s %d %*s %d %*s",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen &t, func, &ret, &usecs);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (c != 4)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* chop the +0xXX/0xXX stuff */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while(func[z] != '+')
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen z++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen func[z] = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (count_only) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* filter out irrelevant stuff */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (usecs >= 1000)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kcount++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen func, t, usecs, ret);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (usecs < 1000)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* rect */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(t - (usecs / 1000000.0)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(kcount),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(usecs / 1000000.0),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(1));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* label */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(t - (usecs / 1000000.0)) + 5,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(kcount) + 15,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen func, usecs / 1000000.0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen kcount++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_ps_bars(FILE *of,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *head,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_samples,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_cpus,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps_first,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double graph_start,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double interval) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int i = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int j = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int pid;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double w = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- Process graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_graph_box(of, head, pcount, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* pass 2 - ps boxes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((ps = get_next_ps(ps, ps_first))) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *enc_name = NULL, *escaped = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double endtime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double starttime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int t;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!utf8_is_printable(ps->name, strlen(ps->name)))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen escaped = utf8_escape_non_printable(ps->name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen enc_name = xml_comment_encode(escaped ? escaped : ps->name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!enc_name)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* leave some trace of what we actually filtered etc. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->ppid, ps->total);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen starttime = ps->first->sampledata->sampletime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps_filter(ps)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* remember where _to_ our children need to draw a line */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->pos_x = time_to_graph(starttime - graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->pos_y = ps_to_graph(j+1); /* bottom left corner */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen } else if (ps->parent){
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* hook children to our parent coords instead */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->pos_x = ps->parent->pos_x;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->pos_y = ps->parent->pos_y;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* if this is the last child, we might still need to draw a connecting line */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((!ps->next) && (ps->parent))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_x,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_x,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_y);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen endtime = ps->last->sampledata->sampletime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(starttime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(ps->last->sampledata->sampletime - starttime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(1));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* paint cpu load over these */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen t = 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double rt, prt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double wt, wrt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_sched_struct *prev;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prev = ps->sample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* calculate over interval */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen rt = ps->sample->runtime - prev->runtime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen wt = ps->sample->waittime - prev->waittime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prt = (rt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen wrt = (wt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* this can happen if timekeeping isn't accurate enough */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (prt > 1.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen prt = 1.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (wrt > 1.0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen wrt = 1.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev->sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(wrt));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* draw cpu over wait - TODO figure out how/why run + wait > interval */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev->sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j + (1.0 - prt)),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(prt));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen t++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* determine where to display the process name */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((endtime - starttime) < 1.5)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* too small to fit label inside the box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen w = endtime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen w = starttime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* text label of process name */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan> %s</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(w - graph_start) + 5.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j) + 14.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen escaped ? escaped : ps->name,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->pid,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (ps->last->runtime - ps->first->runtime) / 1000000000.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen arg_show_cgroup ? ps->cgroup : "");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* paint lines to the parent process */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->parent) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* horizontal part */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(starttime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j) + 10.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_x,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j) + 10.0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* one vertical line connecting all the horizontal ones up */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps->next)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_x,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j) + 10.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_x,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->parent->pos_y);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen j++; /* count boxes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* last pass - determine when idle */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pid = getpid();
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* make sure we start counting from the point where we actually have
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * data: assume that bootchart's first sample is when data started
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->next_ps) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps->next_ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->pid == pid)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* need to know last node first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i = ps->sample->next->sampledata->counter;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next && i<(n_samples-(arg_hz/2))) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double crt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double brt;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int ii;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_sched_struct *sample_hz;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps->sample = ps->sample->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sample_hz = ps->sample;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (ii = 0; (ii < (int)arg_hz/2) && sample_hz->next; ii++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sample_hz = sample_hz->next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* subtract bootchart cpu utilization from total */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen crt = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen brt = sample_hz->runtime - ps->sample->runtime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /*
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * our definition of "idle":
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen *
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * if for (hz / 2) we've used less CPU than (interval / 2) ...
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * defaults to 4.0%, which experimentally, is where atom idles
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((crt - brt) < (interval / 2.0)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen idletime = ps->sample->sampledata->sampletime - graph_start;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n<!-- idle detected at %.03f seconds -->\n", idletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(idletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen -arg_scale_y,
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen time_to_graph(idletime),
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen ps_to_graph(pcount) + arg_scale_y);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(idletime) + 5.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(pcount) + arg_scale_y,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen idletime);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
53fae771bcf1623cd28791c48fa60d9d5e5086e4Zbigniew Jędrzejewski-Szmek }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen i++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
53fae771bcf1623cd28791c48fa60d9d5e5086e4Zbigniew Jędrzejewski-Szmek
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_top_ten_cpu(FILE *of, struct ps_struct *ps_first) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *top[10];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct emptyps = {};
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n, m;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < (int) ELEMENTSOF(top); n++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n] = &emptyps;
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen /* walk all ps's and setup ptrs */
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((ps = get_next_ps(ps, ps_first))) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < 10; n++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->total <= top[n]->total)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
53fae771bcf1623cd28791c48fa60d9d5e5086e4Zbigniew Jędrzejewski-Szmek /* cascade insert */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (m = 9; m > n; m--)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[m] = top[m-1];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n] = ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < 10; n++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen 20 + (n * 13),
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen top[n]->total,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n]->name,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n]->pid);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *top[10];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct emptyps = {};
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n, m;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < (int) ELEMENTSOF(top); n++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n] = &emptyps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* walk all ps's and setup ptrs */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((ps = get_next_ps(ps, ps_first))) {
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen for (n = 0; n < 10; n++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ps->pss_max <= top[n]->pss_max)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
7141e4f62c3f220872df3114c42d9e4b9525e43eTom Gundersen
7141e4f62c3f220872df3114c42d9e4b9525e43eTom Gundersen /* cascade insert */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (m = 9; m > n; m--)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[m] = top[m-1];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n] = ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen break;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < 10; n++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen 20 + (n * 13),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n]->pss_max,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n]->name,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen top[n]->pid);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenint svg_do(FILE *of,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *build,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct list_sample_data *head,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps_first,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_samples,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int pscount,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int n_cpus,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double graph_start,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double log_start,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double interval,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int overrun) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen struct ps_struct *ps;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double offset = 7;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r, c;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sampledata = head;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_FIND_TAIL(link, sampledata, head);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps = ps_first;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* count initcall thread count first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_do_initcall(of, head, 1, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ksize = kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* then count processes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while ((ps = get_next_ps(ps, ps_first))) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!ps_filter(ps))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pcount++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen pfiltered++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen psize = ps_to_graph(pcount) + (arg_scale_y * 2);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen esize = (arg_entropy ? arg_scale_y * 7 : 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* after this, we can draw the header with proper sizing */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_header(of, head, graph_start, arg_percpu ? n_cpus : 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"bg\" width=\"100%%\" height=\"100%%\" />\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,400)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_io_bi_bar(of, head, n_samples, graph_start, interval);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_io_bo_bar(of, head, n_samples, graph_start, interval);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = -1; c < (arg_percpu ? n_cpus : 0); c++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen offset += 7;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_cpu_bar(of, head, n_cpus, c, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen offset += 7;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen svg_wait_bar(of, head, n_cpus, c, graph_start);
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen fprintf(of, "</g>\n\n");
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen }
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (kcount) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen offset += 7;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_do_initcall(of, head, 0, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen offset += 7;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_ps_bars(of, head, n_samples, n_cpus, ps_first, graph_start, interval);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10, 0)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = svg_title(of, build, pscount, log_start, overrun);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,200)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_top_ten_cpu(of, ps_first);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (arg_entropy) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_entropy_bar(of, head, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (arg_pss) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_pss_graph(of, head, ps_first, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(410,200)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen svg_top_ten_pss(of, ps_first);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "</g>\n\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* fprintf footer */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n</svg>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen