2009-09-20 16:15:17

by Arjan van de Ven

[permalink] [raw]
Subject: [git pull] 4 timechart feature patches

Small timechart updated; a few new features and an improvement in performance
that makes inkscape not as slow as it was before.

patches will be posted as reply to this email

The following changes since commit f85b2af8c53ed0f5e0d1008dcea33888d6e22c45:
Ingo Molnar (1):
Merge branch 'out-of-tree'

are available in the git repository at:

ssh://master.kernel.org/pub/scm/linux/kernel/git/arjan/linux-2.6-timechart master

Arjan van de Ven (4):
perf timechart: Show the name of the waker/wakee in timechart
perf timechart: Show the duration of scheduler delays in the SVG
perf util: Make the timechart SVG width dynamic
perf util: SVG performance improvements

tools/perf/Documentation/perf-timechart.txt | 3 +
tools/perf/builtin-timechart.c | 23 +++--
tools/perf/util/svghelper.c | 170 +++++++++++++++++++++-----
tools/perf/util/svghelper.h | 11 +-
4 files changed, 162 insertions(+), 45 deletions(-)

--
Arjan van de Ven Intel Open Source Technology Centre
For development, discussion and tips for power savings,
visit http://www.lesswatts.org


2009-09-20 16:14:39

by Arjan van de Ven

[permalink] [raw]
Subject: [PATCH] perf timechart: Show the name of the waker/wakee in timechart

>From 2d1556e254839707ef701edf21ec8e8116137019 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <[email protected]>
Date: Sat, 19 Sep 2009 19:31:12 +0200
Subject: [PATCH] perf timechart: Show the name of the waker/wakee in timechart

Timechart currently shows thin green lines for sending or receiving wakeups.
This patch also prints (in a very small font) the name of the process that
is being woken/wakes up this process.

Signed-off-by: Arjan van de Ven <[email protected]>
---
tools/perf/builtin-timechart.c | 11 ++++++++---
tools/perf/util/svghelper.c | 28 +++++++++++++++++++++-------
tools/perf/util/svghelper.h | 2 +-
3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 58d737e..3f45b8b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -752,6 +752,7 @@ static void draw_wakeups(void)
we = wake_events;
while (we) {
int from = 0, to = 0;
+ char *task_from = NULL, *task_to = NULL;

/* locate the column of the waker and wakee */
p = all_data;
@@ -760,10 +761,14 @@ static void draw_wakeups(void)
c = p->all;
while (c) {
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
- if (p->pid == we->waker)
+ if (p->pid == we->waker) {
from = c->Y;
- if (p->pid == we->wakee)
+ task_from = c->comm;
+ }
+ if (p->pid == we->wakee) {
to = c->Y;
+ task_to = c->comm;
+ }
}
c = c->next;
}
@@ -776,7 +781,7 @@ static void draw_wakeups(void)
else if (from && to && abs(from - to) == 1)
svg_wakeline(we->time, from, to);
else
- svg_partial_wakeline(we->time, from, to);
+ svg_partial_wakeline(we->time, from, task_from, to, task_to);
we = we->next;
}
}
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index b0fcecd..9f70fa8 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -242,7 +242,7 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
}


-void svg_partial_wakeline(u64 start, int row1, int row2)
+void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
{
double height;

@@ -251,21 +251,35 @@ void svg_partial_wakeline(u64 start, int row1, int row2)


if (row1 < row2) {
- if (row1)
+ if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
-
- if (row2)
+ if (desc2)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
+ }
+ if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
+ if (desc1)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
+ }
} else {
- if (row2)
+ if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
-
- if (row1)
+ if (desc1)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
+ }
+ if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
+ if (desc2)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
+ }
}
height = row1 * SLOT_MULT;
if (row2 > row1)
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index ad79b5d..8260a7e 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -17,7 +17,7 @@ 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_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
extern void svg_interrupt(u64 start, int row);
extern void svg_text(int Yslot, u64 start, const char *text);
extern void svg_close(void);
--
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

2009-09-20 16:14:52

by Arjan van de Ven

[permalink] [raw]
Subject: [PATCH] perf timechart: Show the duration of scheduler delays in the SVG

>From 04d386297c5ffb97a7fcea79cb3300359e4f5dcc Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <[email protected]>
Date: Sat, 19 Sep 2009 20:06:24 +0200
Subject: [PATCH] perf timechart: Show the duration of scheduler delays in the SVG

Given that scheduler latencies are the hot thing nowadays, show the
duration of said latencies in the SVG in text form.

In addition, if the latency is more than 10 msec, pick a brighter
yellow color as a way to point these long delays out.

Signed-off-by: Arjan van de Ven <[email protected]>
---
tools/perf/builtin-timechart.c | 6 ++--
tools/perf/util/svghelper.c | 56 +++++++++++++++++++++++++++++++++++++---
tools/perf/util/svghelper.h | 3 +-
3 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 3f45b8b..23b3f09 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -827,15 +827,15 @@ static void draw_process_bars(void)
continue;
}

- svg_box(Y, p->start_time, p->end_time, "process");
+ svg_box(Y, c->start_time, c->end_time, "process");
sample = c->samples;
while (sample) {
if (sample->type == TYPE_RUNNING)
- svg_sample(Y, sample->cpu, sample->start_time, sample->end_time, "sample");
+ svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
if (sample->type == TYPE_BLOCKED)
svg_box(Y, sample->start_time, sample->end_time, "blocked");
if (sample->type == TYPE_WAITING)
- svg_box(Y, sample->start_time, sample->end_time, "waiting");
+ svg_waiting(Y, sample->start_time, sample->end_time);
sample = sample->next;
}

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 9f70fa8..52f628f 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -69,7 +69,8 @@ void open_svg(const char *filename, int cpus, int rows)
fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
- fprintf(svgfile, " rect.waiting { fill:rgb(255,255, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
+ fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
+ fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
@@ -92,14 +93,14 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type)
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)
+void svg_sample(int Yslot, int cpu, u64 start, u64 end)
{
double text_size;
if (!svgfile)
return;

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
+ fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n",
+ time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT);

text_size = (time2pixels(end)-time2pixels(start));
if (cpu > 9)
@@ -112,6 +113,53 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type)

}

+static char *time_to_string(u64 duration)
+{
+ static char text[80];
+
+ text[0] = 0;
+
+ if (duration < 1000) /* less than 1 usec */
+ return text;
+
+ if (duration < 1000 * 1000) { /* less than 1 msec */
+ sprintf(text, "%4.1f us", duration / 1000.0);
+ return text;
+ }
+ sprintf(text, "%4.1f ms", duration / 1000.0 / 1000);
+
+ return text;
+}
+
+void svg_waiting(int Yslot, u64 start, u64 end)
+{
+ char *text;
+ const char *style;
+ double font_size;
+
+ if (!svgfile)
+ return;
+
+ style = "waiting";
+
+ if (end-start > 10 * 1000000) /* 10 msec */
+ style = "WAITING";
+
+ text = time_to_string(end-start);
+
+ font_size = 1.0 * (time2pixels(end)-time2pixels(start)) / strlen(text);
+
+ if (font_size > 0.2)
+ font_size = 0.2;
+
+
+ fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, style);
+ if (font_size > MIN_TEXT_SIZE)
+ fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%s</text>\n",
+ time2pixels(start), Yslot * SLOT_MULT + 2, font_size, text);
+}
+
static char *cpu_model(void)
{
static char cpu_m[255];
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index 8260a7e..ed4ebcf 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -5,7 +5,8 @@

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_sample(int Yslot, int cpu, u64 start, u64 end);
+extern void svg_waiting(int Yslot, u64 start, u64 end);
extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);


--
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

2009-09-20 16:14:36

by Arjan van de Ven

[permalink] [raw]
Subject: [PATCH] perf util: Make the timechart SVG width dynamic

>From 356f4322f4c6cfee7c708a172fcd22848ad31a1e Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <[email protected]>
Date: Sun, 20 Sep 2009 09:54:58 +0200
Subject: [PATCH] perf util: Make the timechart SVG width dynamic

This patch adds a command line option for timechart that allows the user
to specify the width of the SVG file.

This patch also makes sure that each second of recording has at least 200
units (pixels at 96 DPI) of width. This impacts recordings longer than 5
seconds; recordings shorter than 5 second will scale up to have a width of
1000 units for the whole recording (as before).

Signed-off-by: Arjan van de Ven <[email protected]>
---
tools/perf/Documentation/perf-timechart.txt | 3 ++
tools/perf/builtin-timechart.c | 6 +++-
tools/perf/util/svghelper.c | 30 ++++++++++++++++++---------
tools/perf/util/svghelper.h | 6 +++-
4 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 61e0104..1c2ed30 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -28,6 +28,9 @@ OPTIONS
-i::
--input=::
Select the input file (default: perf.data)
+-w::
+--width=::
+ Select the width of the SVG file (default: 1000)


SEE ALSO
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 23b3f09..6004063 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -915,9 +915,9 @@ static void write_svg_file(const char *filename)
if (count < 15)
count = determine_display_tasks(TIME_THRESH / 10);

- open_svg(filename, numcpus, count);
+ open_svg(filename, numcpus, count, first_time, last_time);

- svg_time_grid(first_time, last_time);
+ svg_time_grid();
svg_legenda();

for (i = 0; i < numcpus; i++)
@@ -1132,6 +1132,8 @@ static const struct option options[] = {
"input file name"),
OPT_STRING('o', "output", &output_name, "file",
"output file name"),
+ OPT_INTEGER('w', "width", &svg_page_width,
+ "page width"),
OPT_END()
};

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 52f628f..be1555e 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -25,7 +25,8 @@ static u64 turbo_frequency, max_freq;

#define SLOT_MULT 30.0
#define SLOT_HEIGHT 25.0
-#define WIDTH 1000.0
+
+int svg_page_width = 1000;

#define MIN_TEXT_SIZE 0.001

@@ -46,21 +47,35 @@ static double time2pixels(u64 time)
{
double X;

- X = WIDTH * (time - first_time) / (last_time - first_time);
+ X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time);
return X;
}

-void open_svg(const char *filename, int cpus, int rows)
+void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
{
+ int new_width;

svgfile = fopen(filename, "w");
if (!svgfile) {
fprintf(stderr, "Cannot open %s for output\n", filename);
return;
}
+ first_time = start;
+ first_time = first_time / 100000000 * 100000000;
+ last_time = end;
+
+ /*
+ * if the recording is short, we default to a width of 1000, but
+ * for longer recordings we want at least 200 units of width per second
+ */
+ new_width = (last_time - first_time) / 5000000;
+
+ if (new_width > svg_page_width)
+ svg_page_width = new_width;
+
total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
- fprintf(svgfile, "<svg width=\"%4.1f\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", WIDTH, total_height);
+ fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);

fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");

@@ -404,15 +419,10 @@ void svg_legenda(void)
svg_legenda_box(800, "Blocked on IO", "blocked");
}

-void svg_time_grid(u64 start, u64 end)
+void svg_time_grid(void)
{
u64 i;

- first_time = start;
- last_time = end;
-
- first_time = first_time / 100000000 * 100000000;
-
if (!svgfile)
return;

diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index ed4ebcf..cd93195 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -3,7 +3,7 @@

#include "types.h"

-extern void open_svg(const char *filename, int cpus, int rows);
+extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
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);
extern void svg_waiting(int Yslot, u64 start, u64 end);
@@ -15,7 +15,7 @@ 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_time_grid(void);
extern void svg_legenda(void);
extern void svg_wakeline(u64 start, int row1, int row2);
extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
@@ -23,4 +23,6 @@ extern void svg_interrupt(u64 start, int row);
extern void svg_text(int Yslot, u64 start, const char *text);
extern void svg_close(void);

+extern int svg_page_width;
+
#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

2009-09-20 16:14:50

by Arjan van de Ven

[permalink] [raw]
Subject: [PATCH] perf util: SVG performance improvements

>From dc31cd02966e59f1db4266e2c25a8bbf6f6e4f5f Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <[email protected]>
Date: Sun, 20 Sep 2009 11:35:53 +0200
Subject: [PATCH] perf util: SVG performance improvements

Tweak the output SVG to increase performance in SVG viewers
by limiting the different types of font sizes and by
smarter transformations on the text.

At least with Inkscape this gives a notable performance improvement
during zoom and scrolling.

Signed-off-by: Arjan van de Ven <[email protected]>
---
tools/perf/util/svghelper.c | 78 ++++++++++++++++++++++++++++++-------------
1 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index be1555e..a778fd0 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -51,6 +51,25 @@ static double time2pixels(u64 time)
return X;
}

+/*
+ * Round text sizes so that the svg viewer only needs a discrete
+ * number of renderings of the font
+ */
+static double round_text_size(double size)
+{
+ int loop = 100;
+ double target = 10.0;
+
+ if (size >= 10.0)
+ return size;
+ while (loop--) {
+ if (size >= target)
+ return target;
+ target = target / 2.0;
+ }
+ return size;
+}
+
void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
{
int new_width;
@@ -122,8 +141,10 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end)
text_size = text_size/2;
if (text_size > 1.25)
text_size = 1.25;
+ text_size = round_text_size(text_size);
+
if (text_size > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%i</text>\n",
+ fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);

}
@@ -162,17 +183,20 @@ void svg_waiting(int Yslot, u64 start, u64 end)

text = time_to_string(end-start);

- font_size = 1.0 * (time2pixels(end)-time2pixels(start)) / strlen(text);
+ font_size = 1.0 * (time2pixels(end)-time2pixels(start));

- if (font_size > 0.2)
- font_size = 0.2;
+ if (font_size > 3)
+ font_size = 3;

+ font_size = round_text_size(font_size);

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, style);
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
+ fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
if (font_size > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%s</text>\n",
- time2pixels(start), Yslot * SLOT_MULT + 2, font_size, text);
+ fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n",
+ font_size, text);
+ fprintf(svgfile, "</g>\n");
}

static char *cpu_model(void)
@@ -211,7 +235,7 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);

sprintf(cpu_string, "CPU %i", (int)cpu+1);
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);

fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
@@ -225,15 +249,21 @@ void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name
if (!svgfile)
return;

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT, type);
+
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
+ fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
width = time2pixels(end)-time2pixels(start);
if (width > 6)
width = 6;

+ width = round_text_size(width);
+
if (width > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">%s</text>\n",
- time2pixels(start), cpu2y(cpu), width, name);
+ fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
+ width, name);
+
+ fprintf(svgfile, "</g>\n");
}

void svg_cstate(int cpu, u64 start, u64 end, int type)
@@ -254,13 +284,15 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
time2pixels(start), time2pixels(end)-time2pixels(start),
cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);

- width = time2pixels(end)-time2pixels(start);
+ width = (time2pixels(end)-time2pixels(start))/2.0;
if (width > 6)
width = 6;

+ width = round_text_size(width);
+
if (width > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">C%i</text>\n",
- time2pixels(start), cpu2y(cpu), width, type);
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
+ time2pixels(start), cpu2y(cpu)+width, width, type);
}

static char *HzToHuman(unsigned long hz)
@@ -299,7 +331,7 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n",
time2pixels(start), time2pixels(end), height, height);
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"0.25pt\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
time2pixels(start), height+0.9, HzToHuman(freq));

}
@@ -318,14 +350,14 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
if (desc2)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
}
if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
if (desc1)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
}
} else {
@@ -333,14 +365,14 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
if (desc1)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
}
if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
if (desc2)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
}
}
@@ -390,7 +422,7 @@ void svg_text(int Yslot, u64 start, const char *text)
if (!svgfile)
return;

- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
}

@@ -401,7 +433,7 @@ static void svg_legenda_box(int X, const char *text, const char *style)

fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
X, boxsize, boxsize, style);
- fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.4fpt\">%s</text>\n",
+ fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
X + boxsize + 5, boxsize, 0.8 * boxsize, text);
}

--
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

2009-09-20 17:40:53

by Arjan van de Ven

[permalink] [raw]
Subject: [tip:perfcounters/urgent] perf timechart: Show the name of the waker/wakee in timechart

Commit-ID: 4f1202c8e61478984ed2d0df616149faf84c2a7f
Gitweb: http://git.kernel.org/tip/4f1202c8e61478984ed2d0df616149faf84c2a7f
Author: Arjan van de Ven <[email protected]>
AuthorDate: Sun, 20 Sep 2009 18:13:28 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 20 Sep 2009 19:37:34 +0200

perf timechart: Show the name of the waker/wakee in timechart

Timechart currently shows thin green lines for sending or receiving
wakeups. This patch also prints (in a very small font) the name of
the process that is being woken/wakes up this process.

Signed-off-by: Arjan van de Ven <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
tools/perf/builtin-timechart.c | 11 ++++++++---
tools/perf/util/svghelper.c | 28 +++++++++++++++++++++-------
tools/perf/util/svghelper.h | 2 +-
3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 58d737e..3f45b8b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -752,6 +752,7 @@ static void draw_wakeups(void)
we = wake_events;
while (we) {
int from = 0, to = 0;
+ char *task_from = NULL, *task_to = NULL;

/* locate the column of the waker and wakee */
p = all_data;
@@ -760,10 +761,14 @@ static void draw_wakeups(void)
c = p->all;
while (c) {
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
- if (p->pid == we->waker)
+ if (p->pid == we->waker) {
from = c->Y;
- if (p->pid == we->wakee)
+ task_from = c->comm;
+ }
+ if (p->pid == we->wakee) {
to = c->Y;
+ task_to = c->comm;
+ }
}
c = c->next;
}
@@ -776,7 +781,7 @@ static void draw_wakeups(void)
else if (from && to && abs(from - to) == 1)
svg_wakeline(we->time, from, to);
else
- svg_partial_wakeline(we->time, from, to);
+ svg_partial_wakeline(we->time, from, task_from, to, task_to);
we = we->next;
}
}
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index b0fcecd..9f70fa8 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -242,7 +242,7 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
}


-void svg_partial_wakeline(u64 start, int row1, int row2)
+void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
{
double height;

@@ -251,21 +251,35 @@ void svg_partial_wakeline(u64 start, int row1, int row2)


if (row1 < row2) {
- if (row1)
+ if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
-
- if (row2)
+ if (desc2)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
+ }
+ if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
+ if (desc1)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
+ }
} else {
- if (row2)
+ if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
-
- if (row1)
+ if (desc1)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
+ }
+ if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
+ if (desc2)
+ fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
+ }
}
height = row1 * SLOT_MULT;
if (row2 > row1)
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index ad79b5d..8260a7e 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -17,7 +17,7 @@ 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_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
extern void svg_interrupt(u64 start, int row);
extern void svg_text(int Yslot, u64 start, const char *text);
extern void svg_close(void);

2009-09-20 17:41:00

by Arjan van de Ven

[permalink] [raw]
Subject: [tip:perfcounters/urgent] perf timechart: Show the duration of scheduler delays in the SVG

Commit-ID: a92fe7b3063db2caa578872fce975ff53aa56214
Gitweb: http://git.kernel.org/tip/a92fe7b3063db2caa578872fce975ff53aa56214
Author: Arjan van de Ven <[email protected]>
AuthorDate: Sun, 20 Sep 2009 18:13:53 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 20 Sep 2009 19:37:35 +0200

perf timechart: Show the duration of scheduler delays in the SVG

Given that scheduler latencies are the hot thing nowadays, show the
duration of said latencies in the SVG in text form.

In addition, if the latency is more than 10 msec, pick a brighter
yellow color as a way to point these long delays out.

Signed-off-by: Arjan van de Ven <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
tools/perf/builtin-timechart.c | 6 ++--
tools/perf/util/svghelper.c | 56 +++++++++++++++++++++++++++++++++++++---
tools/perf/util/svghelper.h | 3 +-
3 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 3f45b8b..23b3f09 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -827,15 +827,15 @@ static void draw_process_bars(void)
continue;
}

- svg_box(Y, p->start_time, p->end_time, "process");
+ svg_box(Y, c->start_time, c->end_time, "process");
sample = c->samples;
while (sample) {
if (sample->type == TYPE_RUNNING)
- svg_sample(Y, sample->cpu, sample->start_time, sample->end_time, "sample");
+ svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
if (sample->type == TYPE_BLOCKED)
svg_box(Y, sample->start_time, sample->end_time, "blocked");
if (sample->type == TYPE_WAITING)
- svg_box(Y, sample->start_time, sample->end_time, "waiting");
+ svg_waiting(Y, sample->start_time, sample->end_time);
sample = sample->next;
}

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 9f70fa8..52f628f 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -69,7 +69,8 @@ void open_svg(const char *filename, int cpus, int rows)
fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
- fprintf(svgfile, " rect.waiting { fill:rgb(255,255, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
+ fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
+ fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
@@ -92,14 +93,14 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type)
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)
+void svg_sample(int Yslot, int cpu, u64 start, u64 end)
{
double text_size;
if (!svgfile)
return;

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
+ fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n",
+ time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT);

text_size = (time2pixels(end)-time2pixels(start));
if (cpu > 9)
@@ -112,6 +113,53 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type)

}

+static char *time_to_string(u64 duration)
+{
+ static char text[80];
+
+ text[0] = 0;
+
+ if (duration < 1000) /* less than 1 usec */
+ return text;
+
+ if (duration < 1000 * 1000) { /* less than 1 msec */
+ sprintf(text, "%4.1f us", duration / 1000.0);
+ return text;
+ }
+ sprintf(text, "%4.1f ms", duration / 1000.0 / 1000);
+
+ return text;
+}
+
+void svg_waiting(int Yslot, u64 start, u64 end)
+{
+ char *text;
+ const char *style;
+ double font_size;
+
+ if (!svgfile)
+ return;
+
+ style = "waiting";
+
+ if (end-start > 10 * 1000000) /* 10 msec */
+ style = "WAITING";
+
+ text = time_to_string(end-start);
+
+ font_size = 1.0 * (time2pixels(end)-time2pixels(start)) / strlen(text);
+
+ if (font_size > 0.2)
+ font_size = 0.2;
+
+
+ fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, style);
+ if (font_size > MIN_TEXT_SIZE)
+ fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%s</text>\n",
+ time2pixels(start), Yslot * SLOT_MULT + 2, font_size, text);
+}
+
static char *cpu_model(void)
{
static char cpu_m[255];
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index 8260a7e..ed4ebcf 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -5,7 +5,8 @@

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_sample(int Yslot, int cpu, u64 start, u64 end);
+extern void svg_waiting(int Yslot, u64 start, u64 end);
extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);

2009-09-20 17:41:08

by Arjan van de Ven

[permalink] [raw]
Subject: [tip:perfcounters/urgent] perf util: Make the timechart SVG width dynamic

Commit-ID: 5094b655452dd48367fb28af74ffc76019b93dc2
Gitweb: http://git.kernel.org/tip/5094b655452dd48367fb28af74ffc76019b93dc2
Author: Arjan van de Ven <[email protected]>
AuthorDate: Sun, 20 Sep 2009 18:14:16 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 20 Sep 2009 19:37:35 +0200

perf util: Make the timechart SVG width dynamic

This patch adds a command line option for timechart that allows the
user to specify the width of the SVG file.

This patch also makes sure that each second of recording has at
least 200 units (pixels at 96 DPI) of width. This impacts
recordings longer than 5 seconds; recordings shorter than 5 second
will scale up to have a width of 1000 units for the whole recording
(as before).

Signed-off-by: Arjan van de Ven <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
tools/perf/Documentation/perf-timechart.txt | 3 ++
tools/perf/builtin-timechart.c | 6 +++-
tools/perf/util/svghelper.c | 30 ++++++++++++++++++---------
tools/perf/util/svghelper.h | 6 +++-
4 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 61e0104..1c2ed30 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -28,6 +28,9 @@ OPTIONS
-i::
--input=::
Select the input file (default: perf.data)
+-w::
+--width=::
+ Select the width of the SVG file (default: 1000)


SEE ALSO
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 23b3f09..6004063 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -915,9 +915,9 @@ static void write_svg_file(const char *filename)
if (count < 15)
count = determine_display_tasks(TIME_THRESH / 10);

- open_svg(filename, numcpus, count);
+ open_svg(filename, numcpus, count, first_time, last_time);

- svg_time_grid(first_time, last_time);
+ svg_time_grid();
svg_legenda();

for (i = 0; i < numcpus; i++)
@@ -1132,6 +1132,8 @@ static const struct option options[] = {
"input file name"),
OPT_STRING('o', "output", &output_name, "file",
"output file name"),
+ OPT_INTEGER('w', "width", &svg_page_width,
+ "page width"),
OPT_END()
};

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 52f628f..be1555e 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -25,7 +25,8 @@ static u64 turbo_frequency, max_freq;

#define SLOT_MULT 30.0
#define SLOT_HEIGHT 25.0
-#define WIDTH 1000.0
+
+int svg_page_width = 1000;

#define MIN_TEXT_SIZE 0.001

@@ -46,21 +47,35 @@ static double time2pixels(u64 time)
{
double X;

- X = WIDTH * (time - first_time) / (last_time - first_time);
+ X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time);
return X;
}

-void open_svg(const char *filename, int cpus, int rows)
+void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
{
+ int new_width;

svgfile = fopen(filename, "w");
if (!svgfile) {
fprintf(stderr, "Cannot open %s for output\n", filename);
return;
}
+ first_time = start;
+ first_time = first_time / 100000000 * 100000000;
+ last_time = end;
+
+ /*
+ * if the recording is short, we default to a width of 1000, but
+ * for longer recordings we want at least 200 units of width per second
+ */
+ new_width = (last_time - first_time) / 5000000;
+
+ if (new_width > svg_page_width)
+ svg_page_width = new_width;
+
total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
- fprintf(svgfile, "<svg width=\"%4.1f\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", WIDTH, total_height);
+ fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);

fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");

@@ -404,15 +419,10 @@ void svg_legenda(void)
svg_legenda_box(800, "Blocked on IO", "blocked");
}

-void svg_time_grid(u64 start, u64 end)
+void svg_time_grid(void)
{
u64 i;

- first_time = start;
- last_time = end;
-
- first_time = first_time / 100000000 * 100000000;
-
if (!svgfile)
return;

diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index ed4ebcf..cd93195 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -3,7 +3,7 @@

#include "types.h"

-extern void open_svg(const char *filename, int cpus, int rows);
+extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
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);
extern void svg_waiting(int Yslot, u64 start, u64 end);
@@ -15,7 +15,7 @@ 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_time_grid(void);
extern void svg_legenda(void);
extern void svg_wakeline(u64 start, int row1, int row2);
extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
@@ -23,4 +23,6 @@ extern void svg_interrupt(u64 start, int row);
extern void svg_text(int Yslot, u64 start, const char *text);
extern void svg_close(void);

+extern int svg_page_width;
+
#endif

2009-09-20 17:41:38

by Arjan van de Ven

[permalink] [raw]
Subject: [tip:perfcounters/urgent] perf util: SVG performance improvements

Commit-ID: 611a546bec3e1af2a87af0862398fc711dc47aef
Gitweb: http://git.kernel.org/tip/611a546bec3e1af2a87af0862398fc711dc47aef
Author: Arjan van de Ven <[email protected]>
AuthorDate: Sun, 20 Sep 2009 18:14:38 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Sun, 20 Sep 2009 19:37:36 +0200

perf util: SVG performance improvements

Tweak the output SVG to increase performance in SVG viewers by
limiting the different types of font sizes and by smarter
transformations on the text.

At least with Inkscape this gives a notable performance improvement
during zoom and scrolling.

Signed-off-by: Arjan van de Ven <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
tools/perf/util/svghelper.c | 78 ++++++++++++++++++++++++++++++-------------
1 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index be1555e..a778fd0 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -51,6 +51,25 @@ static double time2pixels(u64 time)
return X;
}

+/*
+ * Round text sizes so that the svg viewer only needs a discrete
+ * number of renderings of the font
+ */
+static double round_text_size(double size)
+{
+ int loop = 100;
+ double target = 10.0;
+
+ if (size >= 10.0)
+ return size;
+ while (loop--) {
+ if (size >= target)
+ return target;
+ target = target / 2.0;
+ }
+ return size;
+}
+
void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
{
int new_width;
@@ -122,8 +141,10 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end)
text_size = text_size/2;
if (text_size > 1.25)
text_size = 1.25;
+ text_size = round_text_size(text_size);
+
if (text_size > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%i</text>\n",
+ fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);

}
@@ -162,17 +183,20 @@ void svg_waiting(int Yslot, u64 start, u64 end)

text = time_to_string(end-start);

- font_size = 1.0 * (time2pixels(end)-time2pixels(start)) / strlen(text);
+ font_size = 1.0 * (time2pixels(end)-time2pixels(start));

- if (font_size > 0.2)
- font_size = 0.2;
+ if (font_size > 3)
+ font_size = 3;

+ font_size = round_text_size(font_size);

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, style);
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
+ fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
if (font_size > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%s</text>\n",
- time2pixels(start), Yslot * SLOT_MULT + 2, font_size, text);
+ fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n",
+ font_size, text);
+ fprintf(svgfile, "</g>\n");
}

static char *cpu_model(void)
@@ -211,7 +235,7 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);

sprintf(cpu_string, "CPU %i", (int)cpu+1);
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);

fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
@@ -225,15 +249,21 @@ void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name
if (!svgfile)
return;

- fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
- time2pixels(start), time2pixels(end)-time2pixels(start), cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT, type);
+
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
+ fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
+ time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
width = time2pixels(end)-time2pixels(start);
if (width > 6)
width = 6;

+ width = round_text_size(width);
+
if (width > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">%s</text>\n",
- time2pixels(start), cpu2y(cpu), width, name);
+ fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
+ width, name);
+
+ fprintf(svgfile, "</g>\n");
}

void svg_cstate(int cpu, u64 start, u64 end, int type)
@@ -254,13 +284,15 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
time2pixels(start), time2pixels(end)-time2pixels(start),
cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);

- width = time2pixels(end)-time2pixels(start);
+ width = (time2pixels(end)-time2pixels(start))/2.0;
if (width > 6)
width = 6;

+ width = round_text_size(width);
+
if (width > MIN_TEXT_SIZE)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">C%i</text>\n",
- time2pixels(start), cpu2y(cpu), width, type);
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
+ time2pixels(start), cpu2y(cpu)+width, width, type);
}

static char *HzToHuman(unsigned long hz)
@@ -299,7 +331,7 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n",
time2pixels(start), time2pixels(end), height, height);
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"0.25pt\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
time2pixels(start), height+0.9, HzToHuman(freq));

}
@@ -318,14 +350,14 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
if (desc2)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
}
if (row2) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
if (desc1)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &gt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
}
} else {
@@ -333,14 +365,14 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
if (desc1)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
}
if (row1) {
fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
if (desc2)
- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"0.02pt\">%s &lt;</text>\n",
+ fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
}
}
@@ -390,7 +422,7 @@ void svg_text(int Yslot, u64 start, const char *text)
if (!svgfile)
return;

- fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n",
+ fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
}

@@ -401,7 +433,7 @@ static void svg_legenda_box(int X, const char *text, const char *style)

fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
X, boxsize, boxsize, style);
- fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.4fpt\">%s</text>\n",
+ fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
X + boxsize + 5, boxsize, 0.8 * boxsize, text);
}