svg.c revision 4e5356169ac2ef7f22e5a101d86009f706b0ff7b
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright (C) 2009-2013 Intel Corporation
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Auke Kok <auke-jan.h.kok@intel.com>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#define time_to_graph(t) ((t) * arg_scale_x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define ps_to_graph(n) ((n) * arg_scale_y)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering#define kb_to_graph(m) ((m) * arg_scale_y * 0.0001)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#define to_color(n) (192.0 - ((n) * 192.0))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic const char * const colorwheel[12] = {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int pcount = 0;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int kcount = 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic double psize = 0;
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poetteringstatic double ksize = 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic double esize = 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic struct list_sample_data *sampledata;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic struct list_sample_data *prev_sampledata;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic void svg_header(FILE *of, struct list_sample_data *head, double graph_start, int n_cpus) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct list_sample_data *sampledata_last;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* min width is about 1600px due to the label */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering w = 150.0 + 10.0 + time_to_graph(sampledata_last->sampletime - graph_start);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering /* height is variable based on pss, psize, ksize */
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering h = 400.0 + (arg_scale_y * 30.0) /* base graphs and title */
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering + psize + ksize + esize + (n_cpus * 15 * arg_scale_y);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering fprintf(of, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering fprintf(of, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering fprintf(of, "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering //fprintf(of, "<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering fprintf(of, "<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ", w, h);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "xmlns=\"http://www.w3.org/2000/svg\">\n\n");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* write some basic info as a comment, including some help */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek fprintf(of, "<!-- such as Chrome, Chromium, or Firefox. Other applications that -->\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- render these files properly but more slowly are ImageMagick, gimp, -->\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- inkscape, etc. To display the files on your system, just point -->\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- your browser to file:///run/log/ and click. This bootchart was -->\n\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- generated by bootchart version %s, running with options: -->\n", VERSION);
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering fprintf(of, "<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, "<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* style sheet */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect { stroke-width: 1; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.bg { fill: rgb(255,255,255); }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.cpu { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.wait { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.bi { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering fprintf(of, " rect.bo { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.ps { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, " rect.krnl { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " rect.clrw { stroke-width: 0; fill-opacity: 0.7;}\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " line { stroke: rgb(64,64,64); stroke-width: 1; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " line.sec5 { stroke-width: 2; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " line.dot { stroke-dasharray: 2 4; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " line.idle { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " .run { font-size: 8; font-style: italic; }\n");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, " text { font-family: Verdana, Helvetica; font-size: 10; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " text.sec { font-size: 8; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " text.t1 { font-size: 24; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " text.t2 { font-size: 12; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " text.idle { font-size: 18; }\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " ]]>\n </style>\n</defs>\n\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = read_one_line_file("/proc/cmdline", &cmdline);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error_errno(r, "Unable to read cmdline: %m");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* extract root fs so we can find disk model name in sysfs */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* FIXME: this works only in the simple case */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = read_one_line_file(filename, &model);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_info("Error reading disk model for %s: %m\n", rootbdev);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* various utsname parameters */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* CPU type */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = read_full_file("/proc/cpuinfo", &buf, NULL);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return log_error_errno(r, "Unable to read cpuinfo: %m");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering log_error("Unable to read module name from cpuinfo.\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering uts.sysname, uts.release, uts.version, uts.machine);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering 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",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering arg_hz, arg_samples_len, overrun, pscount, pfiltered);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic void svg_graph_box(FILE *of, struct list_sample_data *head, int height, double graph_start) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering double d = 0.0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct list_sample_data *sampledata_last;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering finalsample = sampledata_last->sampletime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* outside box, fill */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering time_to_graph(finalsample - graph_start),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* lines for each second */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i % 50 == 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, " <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (i % 10 == 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, " <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* time label */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (i % 10 == 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering/* xml comments must not contain "--" */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic char* xml_comment_encode(const char* name) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering for (p = enc_name; *p; p++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct list_sample_data *sampledata_last;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fprintf(of, "\n\n<!-- Pss memory size graph -->\n");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fprintf(of, "\n <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* vsize 1000 == 1000mb */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering svg_graph_box(of, head, 100, graph_start);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* draw some hlines for usable memory sizes */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering for (i = 100000; i < 1000000; i += 100000) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering fprintf(of, " <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering time_to_graph(sampledata_last->sampletime - graph_start),
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering time_to_graph(sampledata_last->sampletime - graph_start) + 5,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* now plot the graph itself */
8d90c8a8d6867ffcfb61a11b73205cd7b1a72f3aLennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* put all the small pss blocks into the bottom */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ps->sample->sampledata == sampledata)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (ps->sample->sampledata == sampledata) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (ps->sample->pss <= (100 * arg_scale_y))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ps->sample->pss <= (100 * arg_scale_y))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "rgb(64,64,64)",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering time_to_graph(prev_sampledata->sampletime - graph_start),
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* now plot the ones that are of significant size */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (ps->sample->sampledata == sampledata)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* don't draw anything smaller than 2mb */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (ps->sample->sampledata != sampledata)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (ps->sample->pss > (100 * arg_scale_y)) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering time_to_graph(prev_sampledata->sampletime - graph_start),
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering while ((cross_place = ps->sample->cross)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (ps->sample->pss > (100 * arg_scale_y)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fprintf(of, " <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering time_to_graph(prev_sampledata->sampletime - graph_start),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* overlay all the text labels */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* put all the small pss blocks into the bottom */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (ps->sample->sampledata == sampledata)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (ps->sample->sampledata == sampledata) {
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering if (ps->sample->pss <= (100 * arg_scale_y))
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering while ((cross_place = ps->sample->cross)) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (ps->sample->pss <= (100 * arg_scale_y))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* now plot the ones that are of significant size */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ps->sample->sampledata == sampledata)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* don't draw anything smaller than 2mb */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (ps->sample->sampledata == sampledata) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (ps->sample->pss > (100 * arg_scale_y)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* draw a label with the process / PID */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering time_to_graph(sampledata->sampletime - graph_start),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering while ((cross_place = ps->sample->cross)) {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering if (ps->sample->pss > (100 * arg_scale_y)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* draw a label with the process / PID */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering time_to_graph(sampledata->sampletime - graph_start),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* debug output - full data dump */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, "\n\n<!-- PSS map - csv format -->\n");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fprintf(of, "<!-- %s [%d] pss=", enc_name, ps->pid);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering struct list_sample_data *start_sampledata;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct list_sample_data *stop_sampledata;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- IO utilization graph - In -->\n");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering * calculate rounding range
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * We need to round IO data since IO block data is not updated on
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering * each poll. Applying a smoothing function loses some burst data,
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering * so keep the smoothing range short.
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* surrounding box */
554604b3073467af75dc94fac9e2343148603289Lennart Poettering /* find the max IO first */
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering stop = MIN(i + (range / 2), n_samples - 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start_sampledata = start_sampledata->link_next;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering stop_sampledata = stop_sampledata->link_prev;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start_sampledata = start_sampledata->link_next;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering stop_sampledata = stop_sampledata->link_prev;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
554604b3073467af75dc94fac9e2343148603289Lennart Poettering time_to_graph(prev_sampledata->sampletime - graph_start),
554604b3073467af75dc94fac9e2343148603289Lennart Poettering (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)),
554604b3073467af75dc94fac9e2343148603289Lennart Poettering time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* labels around highest value */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering time_to_graph(sampledata->sampletime - graph_start) + 5,
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering max / 1024.0 / (interval / 1000000000.0));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct list_sample_data *start_sampledata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct list_sample_data *stop_sampledata;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- IO utilization graph - out -->\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * calculate rounding range
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * We need to round IO data since IO block data is not updated on
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * each poll. Applying a smoothing function loses some burst data,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * so keep the smoothing range short.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* surrounding box */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* find the max IO first */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering stop = MIN(i + (range / 2), n_samples - 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start_sampledata = start_sampledata->link_next;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering stop_sampledata = stop_sampledata->link_prev;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start_sampledata = start_sampledata->link_next;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering stop_sampledata = stop_sampledata->link_prev;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering time_to_graph(prev_sampledata->sampletime - graph_start),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* labels around highest bo value */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering time_to_graph(sampledata->sampletime - graph_start) + 5,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering max / 1024.0 / (interval / 1000000000.0));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<!-- CPU utilization graph -->\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* surrounding box */
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek /* bars for each sample, proportional to the CPU util. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_FOREACH_BEFORE(link, sampledata, head) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (c = 0; c < n_cpus; c++)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering trt += sampledata->runtime[c] - prev_sampledata->runtime[c];
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num];
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek time_to_graph(prev_sampledata->sampletime - graph_start),
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sieversstatic void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers fprintf(of, "<!-- Wait time aggregation box -->\n");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers /* surrounding box */
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers /* bars for each sample, proportional to the CPU util. */
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers for (c = 0; c < n_cpus; c++)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers twt += sampledata->waittime[c] - prev_sampledata->waittime[c];
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num];
if (!ps)
return ps;
return NULL;
if (!arg_filter)
static void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) {
int ret;
int usecs;
kcount = 0;
if (!count_only) {
kcount = 0;
while (!feof(f)) {
func[z] = 0;
if (count_only) {
kcount++;
kcount++;
int n_samples,
int n_cpus,
double graph_start,
double interval) {
int pid;
double endtime;
double starttime;
if (!enc_name)
ps_to_graph(j),
ps_to_graph(j),
w = endtime;
w = starttime;
fprintf(of, " <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan> %s</text>\n",
double crt;
double brt;
int ii;
for (c = 0; c < n_cpus; c++)
idletime);
const char *build,
int n_samples,
int pscount,
int n_cpus,
double graph_start,
double log_start,
double interval,
int overrun) {
pcount++;
pfiltered++;
if (kcount) {
if (arg_entropy) {
fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
if (arg_pss) {