Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754142AbZILLFU (ORCPT ); Sat, 12 Sep 2009 07:05:20 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753839AbZILLFT (ORCPT ); Sat, 12 Sep 2009 07:05:19 -0400 Received: from casper.infradead.org ([85.118.1.10]:43152 "EHLO casper.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752338AbZILLEJ convert rfc822-to-8bit (ORCPT ); Sat, 12 Sep 2009 07:04:09 -0400 Date: Sat, 12 Sep 2009 13:06:13 +0200 From: Arjan van de Ven To: linux-kernel@vger.kernel.org Cc: Arjan van de Ven , mingo@elte.hu, fweisbec@gmail.com, peterz@infradead.org Subject: [PATCH 6/8] perf: Add a SVG helper library file Message-ID: <20090912130613.677f0516@infradead.org> In-Reply-To: <20090912130306.5d0086ea@infradead.org> References: <20090912130306.5d0086ea@infradead.org> Organization: Intel X-Mailer: Claws Mail 3.7.2 (GTK+ 2.14.7; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8BIT X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org See http://www.infradead.org/rpr.html Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 15048 Lines: 464 >From 0aeceb5dd0714f68bc8fc120fc010791c670558d Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 12 Sep 2009 12:52:11 +0200 Subject: [PATCH] perf: Add a SVG helper library file The timechart tool writes out SVG format output; this patch adds a set of helper functions to abstract dealing with SVG from the core timechart code. Signed-off-by: Arjan van de Ven --- tools/perf/Makefile | 1 + tools/perf/util/svghelper.c | 382 +++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/svghelper.h | 25 +++ 3 files changed, 408 insertions(+), 0 deletions(-) create mode 100644 tools/perf/util/svghelper.c create mode 100644 tools/perf/util/svghelper.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 9f8d207..a087bf8 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -373,6 +373,7 @@ LIB_OBJS += util/thread.o LIB_OBJS += util/trace-event-parse.o LIB_OBJS += util/trace-event-read.o LIB_OBJS += util/trace-event-info.o +LIB_OBJS += util/svghelper.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c new file mode 100644 index 0000000..20cac41 --- /dev/null +++ b/tools/perf/util/svghelper.c @@ -0,0 +1,382 @@ +/* + * svghelper.c - helper functions for outputting svg + * + * (C) Copyright 2009 Intel Corporation + * + * Authors: + * Arjan van de Ven + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include +#include + +#include "svghelper.h" + +static u64 first_time, last_time; +static u64 turbo_frequency, max_freq; + + +#define SLOT_MULT 30.0 +#define SLOT_HEIGHT 25.0 +#define WIDTH 1000.0 + +static u64 total_height; +static FILE *svgfile; + +static double cpu2slot(int cpu) +{ + return 2 * cpu + 1; +} + +static double cpu2y(int cpu) +{ + return cpu2slot(cpu) * SLOT_MULT; +} + +static double time2pixels(u64 time) +{ + double X; + + X = WIDTH * (time - first_time) / (last_time - first_time); + return X; +} + +void open_svg(const char *filename, int cpus, int rows) +{ + + svgfile = fopen(filename, "w"); + if (!svgfile) { + fprintf(stderr, "Cannot open %s for output\n", filename); + return; + } + total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; + fprintf(svgfile, " \n"); + fprintf(svgfile, "\n", WIDTH, total_height); + + fprintf(svgfile, "\n \n\n"); +} + +void svg_box(int Yslot, u64 start, u64 end, const char *type) +{ + if (!svgfile) + return; + + fprintf(svgfile, "\n", + time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); +} + +void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type) +{ + double text_size; + if (!svgfile) + return; + + fprintf(svgfile, "\n", + time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); + + text_size = (time2pixels(end)-time2pixels(start)); + if (cpu > 9) + text_size = text_size/2; + if (text_size > 1.25) + text_size = 1.25; + if (text_size > 0.001) + fprintf(svgfile, "%i\n", + time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); + +} + +static char *cpu_model(void) +{ + static char cpu_m[255]; + char buf[256]; + FILE *file; + + cpu_m[0] = 0; + /* CPU type */ + file = fopen("/proc/cpuinfo", "r"); + if (file) { + while (fgets(buf, 255, file)) { + if (strstr(buf, "model name")) { + strncpy(cpu_m, &buf[13], 255); + break; + } + } + fclose(file); + } + return cpu_m; +} + +void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) +{ + char cpu_string[80]; + if (!svgfile) + return; + + max_freq = __max_freq; + turbo_frequency = __turbo_freq; + + fprintf(svgfile, "\n", + time2pixels(first_time), + time2pixels(last_time)-time2pixels(first_time), + cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); + + sprintf(cpu_string, "CPU %i", (int)cpu+1); + fprintf(svgfile, "%s\n", + 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); + + fprintf(svgfile, "%s\n", + 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); +} + +void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) +{ + double width; + + if (!svgfile) + return; + + fprintf(svgfile, "\n", + time2pixels(start), time2pixels(end)-time2pixels(start), cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT, type); + width = time2pixels(end)-time2pixels(start); + if (width > 6) + width = 6; + + if (width > 0.1) + fprintf(svgfile, "%s\n", + time2pixels(start), cpu2y(cpu), width, name); +} + +void svg_cstate(int cpu, u64 start, u64 end, int type) +{ + double width; + char style[128]; + + if (!svgfile) + return; + + + if (type > 6) + type = 6; + sprintf(style, "c%i", type); + + fprintf(svgfile, "\n", + style, + time2pixels(start), time2pixels(end)-time2pixels(start), + cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); + + width = time2pixels(end)-time2pixels(start); + if (width > 6) + width = 6; + + if (width > 0.05) + fprintf(svgfile, "C%i\n", + time2pixels(start), cpu2y(cpu), width, type); +} + +static char *HzToHuman(unsigned long hz) +{ + static char buffer[1024]; + unsigned long long Hz; + + memset(buffer, 0, 1024); + + Hz = hz; + + /* default: just put the Number in */ + sprintf(buffer, "%9lli", Hz); + + if (Hz > 1000) + sprintf(buffer, " %6lli Mhz", (Hz+500)/1000); + + if (Hz > 1500000) + sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000); + + if (Hz == turbo_frequency) + sprintf(buffer, "Turbo"); + + return buffer; +} + +void svg_pstate(int cpu, u64 start, u64 end, u64 freq) +{ + double height = 0; + + if (!svgfile) + return; + + if (max_freq) + height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); + height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; + fprintf(svgfile, "\n", + time2pixels(start), time2pixels(end), height, height); + fprintf(svgfile, "%s\n", + time2pixels(start), height+0.9, HzToHuman(freq)); + +} + + +void svg_partial_wakeline(u64 start, int row1, int row2) +{ + double height; + + if (!svgfile) + return; + + + if (row1 < row2) { + if (row1) + fprintf(svgfile, "\n", + time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); + + if (row2) + fprintf(svgfile, "\n", + time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT); + } else { + if (row2) + fprintf(svgfile, "\n", + time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); + + if (row1) + fprintf(svgfile, "\n", + time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT); + } + height = row1 * SLOT_MULT; + if (row2 > row1) + height += SLOT_HEIGHT; + if (row1) + fprintf(svgfile, "\n", + time2pixels(start), height); +} + +void svg_wakeline(u64 start, int row1, int row2) +{ + double height; + + if (!svgfile) + return; + + + if (row1 < row2) + fprintf(svgfile, "\n", + time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); + else + fprintf(svgfile, "\n", + time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT); + + height = row1 * SLOT_MULT; + if (row2 > row1) + height += SLOT_HEIGHT; + fprintf(svgfile, "\n", + time2pixels(start), height); +} + +void svg_interrupt(u64 start, int row) +{ + if (!svgfile) + return; + + fprintf(svgfile, "\n", + time2pixels(start), row * SLOT_MULT); + fprintf(svgfile, "\n", + time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); +} + +void svg_text(int Yslot, u64 start, const char *text) +{ + if (!svgfile) + return; + + fprintf(svgfile, "%s\n", + time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text); +} + +static void svg_legenda_box(int X, const char *text, const char *style) +{ + double boxsize; + boxsize = SLOT_HEIGHT / 2; + + fprintf(svgfile, "\n", + X, boxsize, boxsize, style); + fprintf(svgfile, "%s\n", + X + boxsize + 5, boxsize, 0.8 * boxsize, text); +} + +void svg_legenda(void) +{ + if (!svgfile) + return; + + svg_legenda_box(0, "Running", "sample"); + svg_legenda_box(100, "Idle","rect.c1"); + svg_legenda_box(200, "Deeper Idle", "rect.c3"); + svg_legenda_box(350, "Deepest Idle", "rect.c6"); + svg_legenda_box(550, "Sleeping", "process2"); + svg_legenda_box(650, "Waiting for cpu", "waiting"); + svg_legenda_box(800, "Blocked on IO", "blocked"); +} + +void svg_time_grid(u64 start, u64 end) +{ + u64 i; + + first_time = start; + last_time = end; + + first_time = first_time / 100000000 * 100000000; + + if (!svgfile) + return; + + i = first_time; + while (i < last_time) { + int color = 220; + double thickness = 0.075; + if ((i % 100000000) == 0) { + thickness = 0.5; + color = 192; + } + if ((i % 1000000000) == 0) { + thickness = 2.0; + color = 128; + } + + fprintf(svgfile, "\n", + time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness); + + i += 10000000; + } +} + +void svg_close(void) +{ + if (svgfile) { + fprintf(svgfile, "\n"); + fclose(svgfile); + svgfile = NULL; + } +} diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h new file mode 100644 index 0000000..ad79b5d --- /dev/null +++ b/tools/perf/util/svghelper.h @@ -0,0 +1,25 @@ +#ifndef _INCLUDE_GUARD_SVG_HELPER_ +#define _INCLUDE_GUARD_SVG_HELPER_ + +#include "types.h" + +extern void open_svg(const char *filename, int cpus, int rows); +extern void svg_box(int Yslot, u64 start, u64 end, const char *type); +extern void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type); +extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); + + +extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); +extern void svg_cstate(int cpu, u64 start, u64 end, int type); +extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); + + +extern void svg_time_grid(u64 start, u64 end); +extern void svg_legenda(void); +extern void svg_wakeline(u64 start, int row1, int row2); +extern void svg_partial_wakeline(u64 start, int row1, int row2); +extern void svg_interrupt(u64 start, int row); +extern void svg_text(int Yslot, u64 start, const char *text); +extern void svg_close(void); + +#endif -- 1.6.0.6 -- Arjan van de Ven Intel Open Source Technology Centre For development, discussion and tips for power savings, visit http://www.lesswatts.org -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/