svg.c revision f2d28e80bc6260c90396e9fc798d559775dbde23
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen This file is part of systemd.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Copyright (C) 2009-2013 Intel Corporation
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Auke Kok <auke-jan.h.kok@intel.com>
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 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 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#define kb_to_graph(m) ((m) * arg_scale_y * 0.0001)
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 *prev_sampledata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_header(FILE *of, struct list_sample_data *head, double graph_start, int n_cpus) {
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 /* 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 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 //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 /* 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 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 /* style sheet */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<defs>\n <style type=\"text/css\">\n <![CDATA[\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.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 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.idle { font-size: 18; }\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *cpu;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = read_one_line_file("/proc/cmdline", &cmdline);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error_errno(r, "Unable to read cmdline: %m");
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen /* extract root fs so we can find disk model name in sysfs */
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen /* FIXME: this works only in the simple case */
08232a020bd2571088d3ee06dda07732c5e963d1Tom Gundersen strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_info("Error reading disk model for %s: %m\n", rootbdev);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* various utsname parameters */
52d629010db73a9466c359201916494bd55186d1Tom Gundersen r = strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* CPU type */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
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 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 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 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 /* outside box, fill */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
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 else if (i % 10 == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
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/* xml comments must not contain "--" */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic char* xml_comment_encode(const char* name) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (p = enc_name; *p; p++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n\n<!-- Pss memory size graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* vsize 1000 == 1000mb */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* draw some hlines for usable memory sizes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata_last->sampletime - graph_start),
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 /* now plot the graph itself */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* put all the small pss blocks into the bottom */
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 time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* now plot the ones that are of significant size */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't draw anything smaller than 2mb */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(prev_sampledata->sampletime - graph_start),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* overlay all the text labels */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* put all the small pss blocks into the bottom */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* now plot the ones that are of significant size */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't draw anything smaller than 2mb */
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 /* 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 /* debug output - full data dump */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "\n\n<!-- PSS map - csv format -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- %s [%d] pss=", enc_name, ps->pid);
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 * calculate rounding range
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 /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find the max IO first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* plot bi */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
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 /* labels around highest value */
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 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 * calculate rounding range
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 /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find the max IO first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* plot bo */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen start_sampledata = start_sampledata->link_next;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
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 /* labels around highest bo value */
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 Gundersenstatic void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- CPU utilization graph -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, proportional to the CPU util. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt += sampledata->runtime[c] - prev_sampledata->runtime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime);
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 Gundersenstatic void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- Wait time aggregation box -->\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, proportional to the CPU util. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt += sampledata->waittime[c] - prev_sampledata->waittime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime);
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 Gundersenstatic void svg_entropy_bar(FILE *of, struct list_sample_data *head, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* bars for each sample, scale 0-4096 */
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 Gundersenstatic struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_first) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * walk the list of processes and return the next one to be
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* go deep */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* find siblings */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* go back for parent siblings */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return false;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* can't draw data when there is only 1 sample (need start + stop) */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* don't filter kthreadd */
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen return false;
7283a80d10217b929acf58899f016ca06dacdc53Tom Gundersen /* drop stuff that doesn't use any real CPU time */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* can't plot initcall when disabled or in relative mode */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
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 while (!feof(f)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen c = sscanf(l, "[%lf] initcall %s %*s %d %*s %d %*s",
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 /* chop the +0xXX/0xXX stuff */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* filter out irrelevant stuff */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen double w = 0.0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* surrounding box */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* pass 2 - ps boxes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *enc_name = NULL, *escaped = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!utf8_is_printable(ps->name, strlen(ps->name)))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen escaped = utf8_escape_non_printable(ps->name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen enc_name = xml_comment_encode(escaped ? escaped : ps->name);
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 starttime = ps->first->sampledata->sampletime;
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 /* hook children to our parent coords instead */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* if this is the last child, we might still need to draw a connecting line */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen time_to_graph(ps->last->sampledata->sampletime - starttime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* paint cpu load over these */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* calculate over interval */
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 /* this can happen if timekeeping isn't accurate enough */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */
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 time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
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 time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* determine where to display the process name */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* too small to fit label inside the box */
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 (ps->last->runtime - ps->first->runtime) / 1000000000.0,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* paint lines to the parent process */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* horizontal part */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* one vertical line connecting all the horizontal ones up */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, " <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen j++; /* count boxes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* last pass - determine when idle */
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 /* need to know last node first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen while (ps->sample->next && i<(n_samples-(arg_hz/2))) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (ii = 0; (ii < (int)arg_hz/2) && sample_hz->next; ii++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* subtract bootchart cpu utilization from total */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (c = 0; c < n_cpus; c++)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen brt = sample_hz->runtime - ps->sample->runtime;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * our definition of "idle":
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 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 fprintf(of, "<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void svg_top_ten_cpu(FILE *of, struct ps_struct *ps_first) {
4189708ad0cde8e211e38d27de943579772f8869Tom Gundersen /* walk all ps's and setup ptrs */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (n = 0; n < 10; n++) {
53fae771bcf1623cd28791c48fa60d9d5e5086e4Zbigniew Jędrzejewski-Szmek /* cascade insert */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (m = 9; m > n; m--)
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 Gundersenstatic void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* walk all ps's and setup ptrs */
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen for (n = 0; n < 10; n++) {
7141e4f62c3f220872df3114c42d9e4b9525e43eTom Gundersen /* cascade insert */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (m = 9; m > n; m--)
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 /* count initcall thread count first */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ksize = kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* then count processes */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen psize = ps_to_graph(pcount) + (arg_scale_y * 2);
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 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 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 for (c = -1; c < (arg_percpu ? n_cpus : 0); c++) {
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 transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
107f2e2526d476c6cc9b81a690391c111027d641Tom Gundersen svg_wait_bar(of, head, n_cpus, c, graph_start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
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 transform=\"translate(10, 0)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = svg_title(of, build, pscount, log_start, overrun);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,200)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
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 transform=\"translate(410,200)\">\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* fprintf footer */