diff options
-rw-r--r-- | tools/perf/Documentation/perf-timechart.txt | 13 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 21 | ||||
-rw-r--r-- | tools/perf/util/svghelper.c | 23 | ||||
-rw-r--r-- | tools/perf/util/svghelper.h | 4 |
4 files changed, 56 insertions, 5 deletions
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt index 367c1be0551c..bc5990c33dc0 100644 --- a/tools/perf/Documentation/perf-timechart.txt +++ b/tools/perf/Documentation/perf-timechart.txt | |||
@@ -56,12 +56,25 @@ $ perf timechart | |||
56 | 56 | ||
57 | Written 10.2 seconds of trace to output.svg. | 57 | Written 10.2 seconds of trace to output.svg. |
58 | 58 | ||
59 | Record system-wide timechart: | ||
60 | |||
61 | $ perf timechart record | ||
62 | |||
63 | then generate timechart and highlight 'gcc' tasks: | ||
64 | |||
65 | $ perf timechart --highlight gcc | ||
66 | |||
59 | -n:: | 67 | -n:: |
60 | --proc-num:: | 68 | --proc-num:: |
61 | Print task info for at least given number of tasks. | 69 | Print task info for at least given number of tasks. |
62 | -t:: | 70 | -t:: |
63 | --topology:: | 71 | --topology:: |
64 | Sort CPUs according to topology. | 72 | Sort CPUs according to topology. |
73 | --highlight=<duration_nsecs|task_name>:: | ||
74 | Highlight tasks (using different color) that run more than given | ||
75 | duration or tasks with given name. If number is given it's interpreted | ||
76 | as number of nanoseconds. If non-numeric string is given it's | ||
77 | interpreted as task name. | ||
65 | 78 | ||
66 | RECORD OPTIONS | 79 | RECORD OPTIONS |
67 | -------------- | 80 | -------------- |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 8bde57c5c908..20d4212fa337 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -841,7 +841,6 @@ static void draw_cpu_usage(struct timechart *tchart) | |||
841 | sample->start_time, | 841 | sample->start_time, |
842 | sample->end_time, | 842 | sample->end_time, |
843 | p->pid, | 843 | p->pid, |
844 | "sample", | ||
845 | c->comm, | 844 | c->comm, |
846 | sample->backtrace); | 845 | sample->backtrace); |
847 | } | 846 | } |
@@ -1252,6 +1251,23 @@ parse_process(const struct option *opt __maybe_unused, const char *arg, | |||
1252 | return 0; | 1251 | return 0; |
1253 | } | 1252 | } |
1254 | 1253 | ||
1254 | static int | ||
1255 | parse_highlight(const struct option *opt __maybe_unused, const char *arg, | ||
1256 | int __maybe_unused unset) | ||
1257 | { | ||
1258 | unsigned long duration = strtoul(arg, NULL, 0); | ||
1259 | |||
1260 | if (svg_highlight || svg_highlight_name) | ||
1261 | return -1; | ||
1262 | |||
1263 | if (duration) | ||
1264 | svg_highlight = duration; | ||
1265 | else | ||
1266 | svg_highlight_name = strdup(arg); | ||
1267 | |||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1255 | int cmd_timechart(int argc, const char **argv, | 1271 | int cmd_timechart(int argc, const char **argv, |
1256 | const char *prefix __maybe_unused) | 1272 | const char *prefix __maybe_unused) |
1257 | { | 1273 | { |
@@ -1270,6 +1286,9 @@ int cmd_timechart(int argc, const char **argv, | |||
1270 | OPT_STRING('i', "input", &input_name, "file", "input file name"), | 1286 | OPT_STRING('i', "input", &input_name, "file", "input file name"), |
1271 | OPT_STRING('o', "output", &output_name, "file", "output file name"), | 1287 | OPT_STRING('o', "output", &output_name, "file", "output file name"), |
1272 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), | 1288 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), |
1289 | OPT_CALLBACK(0, "highlight", NULL, "duration or task name", | ||
1290 | "highlight tasks. Pass duration in ns or process name.", | ||
1291 | parse_highlight), | ||
1273 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), | 1292 | OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), |
1274 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, | 1293 | OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, |
1275 | "output processes data only"), | 1294 | "output processes data only"), |
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 9468136735ca..56a84f2cc46d 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
@@ -31,6 +31,8 @@ static u64 turbo_frequency, max_freq; | |||
31 | #define SLOT_HEIGHT 25.0 | 31 | #define SLOT_HEIGHT 25.0 |
32 | 32 | ||
33 | int svg_page_width = 1000; | 33 | int svg_page_width = 1000; |
34 | u64 svg_highlight; | ||
35 | const char *svg_highlight_name; | ||
34 | 36 | ||
35 | #define MIN_TEXT_SIZE 0.01 | 37 | #define MIN_TEXT_SIZE 0.01 |
36 | 38 | ||
@@ -112,6 +114,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | |||
112 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); | 114 | fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); |
113 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 115 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
114 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 116 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
117 | fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | ||
115 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 118 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
116 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 119 | fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
117 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 120 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
@@ -155,17 +158,24 @@ void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | |||
155 | void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) | 158 | void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) |
156 | { | 159 | { |
157 | double text_size; | 160 | double text_size; |
161 | const char *type; | ||
162 | |||
158 | if (!svgfile) | 163 | if (!svgfile) |
159 | return; | 164 | return; |
160 | 165 | ||
166 | if (svg_highlight && end - start > svg_highlight) | ||
167 | type = "sample_hi"; | ||
168 | else | ||
169 | type = "sample"; | ||
161 | fprintf(svgfile, "<g>\n"); | 170 | fprintf(svgfile, "<g>\n"); |
162 | 171 | ||
163 | fprintf(svgfile, "<title>#%d running %s</title>\n", | 172 | fprintf(svgfile, "<title>#%d running %s</title>\n", |
164 | cpu, time_to_string(end - start)); | 173 | cpu, time_to_string(end - start)); |
165 | if (backtrace) | 174 | if (backtrace) |
166 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); | 175 | fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); |
167 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", | 176 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", |
168 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); | 177 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, |
178 | type); | ||
169 | 179 | ||
170 | text_size = (time2pixels(end)-time2pixels(start)); | 180 | text_size = (time2pixels(end)-time2pixels(start)); |
171 | if (cpu > 9) | 181 | if (cpu > 9) |
@@ -293,13 +303,20 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) | |||
293 | fprintf(svgfile, "</g>\n"); | 303 | fprintf(svgfile, "</g>\n"); |
294 | } | 304 | } |
295 | 305 | ||
296 | void svg_process(int cpu, u64 start, u64 end, int pid, const char *type, const char *name, const char *backtrace) | 306 | void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace) |
297 | { | 307 | { |
298 | double width; | 308 | double width; |
309 | const char *type; | ||
299 | 310 | ||
300 | if (!svgfile) | 311 | if (!svgfile) |
301 | return; | 312 | return; |
302 | 313 | ||
314 | if (svg_highlight && end - start >= svg_highlight) | ||
315 | type = "sample_hi"; | ||
316 | else if (svg_highlight_name && strstr(name, svg_highlight_name)) | ||
317 | type = "sample_hi"; | ||
318 | else | ||
319 | type = "sample"; | ||
303 | 320 | ||
304 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); | 321 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); |
305 | fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start)); | 322 | fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start)); |
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h index 1df4fb6c3a4a..f7b4d6e699ea 100644 --- a/tools/perf/util/svghelper.h +++ b/tools/perf/util/svghelper.h | |||
@@ -11,7 +11,7 @@ extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *back | |||
11 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); | 11 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); |
12 | 12 | ||
13 | 13 | ||
14 | extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *type, const char *name, const char *backtrace); | 14 | extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace); |
15 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); | 15 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); |
16 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); | 16 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); |
17 | 17 | ||
@@ -27,5 +27,7 @@ extern int svg_build_topology_map(char *sib_core, int sib_core_nr, | |||
27 | char *sib_thr, int sib_thr_nr); | 27 | char *sib_thr, int sib_thr_nr); |
28 | 28 | ||
29 | extern int svg_page_width; | 29 | extern int svg_page_width; |
30 | extern u64 svg_highlight; | ||
31 | extern const char *svg_highlight_name; | ||
30 | 32 | ||
31 | #endif /* __PERF_SVGHELPER_H */ | 33 | #endif /* __PERF_SVGHELPER_H */ |