diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:06:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-21 12:06:31 -0400 |
commit | f4eccb6d979e0cc5a719a50af5f9a56e79092a2d (patch) | |
tree | 00b3ca17251430ce1336d813cf76e95ccdd55099 | |
parent | 8e4bc3dd2ca07d77882eba73cea240aba95a1854 (diff) | |
parent | cd74c86bdf705f824d494a2bbda393d1d562b40a (diff) |
Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf_counter, powerpc, sparc: Fix compilation after perf_counter_overflow() change
perf_counter: x86: Fix PMU resource leak
perf util: SVG performance improvements
perf util: Make the timechart SVG width dynamic
perf timechart: Show the duration of scheduler delays in the SVG
perf timechart: Show the name of the waker/wakee in timechart
-rw-r--r-- | arch/powerpc/kernel/perf_counter.c | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/perf_counter.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 9 | ||||
-rw-r--r-- | include/linux/perf_counter.h | 17 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-timechart.txt | 3 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 23 | ||||
-rw-r--r-- | tools/perf/util/svghelper.c | 170 | ||||
-rw-r--r-- | tools/perf/util/svghelper.h | 11 |
8 files changed, 170 insertions, 69 deletions
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c index 7ceefaf3a7f5..5ccf9bca96c0 100644 --- a/arch/powerpc/kernel/perf_counter.c +++ b/arch/powerpc/kernel/perf_counter.c | |||
@@ -1162,7 +1162,6 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val, | |||
1162 | */ | 1162 | */ |
1163 | if (record) { | 1163 | if (record) { |
1164 | struct perf_sample_data data = { | 1164 | struct perf_sample_data data = { |
1165 | .regs = regs, | ||
1166 | .addr = 0, | 1165 | .addr = 0, |
1167 | .period = counter->hw.last_period, | 1166 | .period = counter->hw.last_period, |
1168 | }; | 1167 | }; |
@@ -1170,7 +1169,7 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val, | |||
1170 | if (counter->attr.sample_type & PERF_SAMPLE_ADDR) | 1169 | if (counter->attr.sample_type & PERF_SAMPLE_ADDR) |
1171 | perf_get_data_addr(regs, &data.addr); | 1170 | perf_get_data_addr(regs, &data.addr); |
1172 | 1171 | ||
1173 | if (perf_counter_overflow(counter, nmi, &data)) { | 1172 | if (perf_counter_overflow(counter, nmi, &data, regs)) { |
1174 | /* | 1173 | /* |
1175 | * Interrupts are coming too fast - throttle them | 1174 | * Interrupts are coming too fast - throttle them |
1176 | * by setting the counter to 0, so it will be | 1175 | * by setting the counter to 0, so it will be |
diff --git a/arch/sparc/kernel/perf_counter.c b/arch/sparc/kernel/perf_counter.c index 09de4035eaa9..b1265ce8a053 100644 --- a/arch/sparc/kernel/perf_counter.c +++ b/arch/sparc/kernel/perf_counter.c | |||
@@ -493,7 +493,6 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self, | |||
493 | 493 | ||
494 | regs = args->regs; | 494 | regs = args->regs; |
495 | 495 | ||
496 | data.regs = regs; | ||
497 | data.addr = 0; | 496 | data.addr = 0; |
498 | 497 | ||
499 | cpuc = &__get_cpu_var(cpu_hw_counters); | 498 | cpuc = &__get_cpu_var(cpu_hw_counters); |
@@ -513,7 +512,7 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self, | |||
513 | if (!sparc_perf_counter_set_period(counter, hwc, idx)) | 512 | if (!sparc_perf_counter_set_period(counter, hwc, idx)) |
514 | continue; | 513 | continue; |
515 | 514 | ||
516 | if (perf_counter_overflow(counter, 1, &data)) | 515 | if (perf_counter_overflow(counter, 1, &data, regs)) |
517 | sparc_pmu_disable_counter(hwc, idx); | 516 | sparc_pmu_disable_counter(hwc, idx); |
518 | } | 517 | } |
519 | 518 | ||
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index dbdf712fae9e..a6c8b27553cd 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -924,6 +924,8 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
924 | if (err) | 924 | if (err) |
925 | return err; | 925 | return err; |
926 | 926 | ||
927 | counter->destroy = hw_perf_counter_destroy; | ||
928 | |||
927 | /* | 929 | /* |
928 | * Generate PMC IRQs: | 930 | * Generate PMC IRQs: |
929 | * (keep 'enabled' bit clear for now) | 931 | * (keep 'enabled' bit clear for now) |
@@ -953,8 +955,6 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
953 | return -EOPNOTSUPP; | 955 | return -EOPNOTSUPP; |
954 | } | 956 | } |
955 | 957 | ||
956 | counter->destroy = hw_perf_counter_destroy; | ||
957 | |||
958 | /* | 958 | /* |
959 | * Raw event type provide the config in the event structure | 959 | * Raw event type provide the config in the event structure |
960 | */ | 960 | */ |
@@ -2107,8 +2107,11 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | |||
2107 | int err; | 2107 | int err; |
2108 | 2108 | ||
2109 | err = __hw_perf_counter_init(counter); | 2109 | err = __hw_perf_counter_init(counter); |
2110 | if (err) | 2110 | if (err) { |
2111 | if (counter->destroy) | ||
2112 | counter->destroy(counter); | ||
2111 | return ERR_PTR(err); | 2113 | return ERR_PTR(err); |
2114 | } | ||
2112 | 2115 | ||
2113 | return &pmu; | 2116 | return &pmu; |
2114 | } | 2117 | } |
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index bd341007c4fc..740caad09a44 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -849,23 +849,6 @@ static inline void perf_counter_comm(struct task_struct *tsk) { } | |||
849 | static inline void perf_counter_fork(struct task_struct *tsk) { } | 849 | static inline void perf_counter_fork(struct task_struct *tsk) { } |
850 | static inline void perf_counter_init(void) { } | 850 | static inline void perf_counter_init(void) { } |
851 | 851 | ||
852 | static inline int | ||
853 | perf_output_begin(struct perf_output_handle *handle, struct perf_counter *c, | ||
854 | unsigned int size, int nmi, int sample) { } | ||
855 | static inline void perf_output_end(struct perf_output_handle *handle) { } | ||
856 | static inline void | ||
857 | perf_output_copy(struct perf_output_handle *handle, | ||
858 | const void *buf, unsigned int len) { } | ||
859 | static inline void | ||
860 | perf_output_sample(struct perf_output_handle *handle, | ||
861 | struct perf_event_header *header, | ||
862 | struct perf_sample_data *data, | ||
863 | struct perf_counter *counter) { } | ||
864 | static inline void | ||
865 | perf_prepare_sample(struct perf_event_header *header, | ||
866 | struct perf_sample_data *data, | ||
867 | struct perf_counter *counter, | ||
868 | struct pt_regs *regs) { } | ||
869 | #endif | 852 | #endif |
870 | 853 | ||
871 | #define perf_output_put(handle, x) \ | 854 | #define perf_output_put(handle, x) \ |
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt index 61e0104c6270..1c2ed3090cce 100644 --- a/tools/perf/Documentation/perf-timechart.txt +++ b/tools/perf/Documentation/perf-timechart.txt | |||
@@ -28,6 +28,9 @@ OPTIONS | |||
28 | -i:: | 28 | -i:: |
29 | --input=:: | 29 | --input=:: |
30 | Select the input file (default: perf.data) | 30 | Select the input file (default: perf.data) |
31 | -w:: | ||
32 | --width=:: | ||
33 | Select the width of the SVG file (default: 1000) | ||
31 | 34 | ||
32 | 35 | ||
33 | SEE ALSO | 36 | SEE ALSO |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 58d737ec8f5e..600406396274 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -752,6 +752,7 @@ static void draw_wakeups(void) | |||
752 | we = wake_events; | 752 | we = wake_events; |
753 | while (we) { | 753 | while (we) { |
754 | int from = 0, to = 0; | 754 | int from = 0, to = 0; |
755 | char *task_from = NULL, *task_to = NULL; | ||
755 | 756 | ||
756 | /* locate the column of the waker and wakee */ | 757 | /* locate the column of the waker and wakee */ |
757 | p = all_data; | 758 | p = all_data; |
@@ -760,10 +761,14 @@ static void draw_wakeups(void) | |||
760 | c = p->all; | 761 | c = p->all; |
761 | while (c) { | 762 | while (c) { |
762 | if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { | 763 | if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { |
763 | if (p->pid == we->waker) | 764 | if (p->pid == we->waker) { |
764 | from = c->Y; | 765 | from = c->Y; |
765 | if (p->pid == we->wakee) | 766 | task_from = c->comm; |
767 | } | ||
768 | if (p->pid == we->wakee) { | ||
766 | to = c->Y; | 769 | to = c->Y; |
770 | task_to = c->comm; | ||
771 | } | ||
767 | } | 772 | } |
768 | c = c->next; | 773 | c = c->next; |
769 | } | 774 | } |
@@ -776,7 +781,7 @@ static void draw_wakeups(void) | |||
776 | else if (from && to && abs(from - to) == 1) | 781 | else if (from && to && abs(from - to) == 1) |
777 | svg_wakeline(we->time, from, to); | 782 | svg_wakeline(we->time, from, to); |
778 | else | 783 | else |
779 | svg_partial_wakeline(we->time, from, to); | 784 | svg_partial_wakeline(we->time, from, task_from, to, task_to); |
780 | we = we->next; | 785 | we = we->next; |
781 | } | 786 | } |
782 | } | 787 | } |
@@ -822,15 +827,15 @@ static void draw_process_bars(void) | |||
822 | continue; | 827 | continue; |
823 | } | 828 | } |
824 | 829 | ||
825 | svg_box(Y, p->start_time, p->end_time, "process"); | 830 | svg_box(Y, c->start_time, c->end_time, "process"); |
826 | sample = c->samples; | 831 | sample = c->samples; |
827 | while (sample) { | 832 | while (sample) { |
828 | if (sample->type == TYPE_RUNNING) | 833 | if (sample->type == TYPE_RUNNING) |
829 | svg_sample(Y, sample->cpu, sample->start_time, sample->end_time, "sample"); | 834 | svg_sample(Y, sample->cpu, sample->start_time, sample->end_time); |
830 | if (sample->type == TYPE_BLOCKED) | 835 | if (sample->type == TYPE_BLOCKED) |
831 | svg_box(Y, sample->start_time, sample->end_time, "blocked"); | 836 | svg_box(Y, sample->start_time, sample->end_time, "blocked"); |
832 | if (sample->type == TYPE_WAITING) | 837 | if (sample->type == TYPE_WAITING) |
833 | svg_box(Y, sample->start_time, sample->end_time, "waiting"); | 838 | svg_waiting(Y, sample->start_time, sample->end_time); |
834 | sample = sample->next; | 839 | sample = sample->next; |
835 | } | 840 | } |
836 | 841 | ||
@@ -910,9 +915,9 @@ static void write_svg_file(const char *filename) | |||
910 | if (count < 15) | 915 | if (count < 15) |
911 | count = determine_display_tasks(TIME_THRESH / 10); | 916 | count = determine_display_tasks(TIME_THRESH / 10); |
912 | 917 | ||
913 | open_svg(filename, numcpus, count); | 918 | open_svg(filename, numcpus, count, first_time, last_time); |
914 | 919 | ||
915 | svg_time_grid(first_time, last_time); | 920 | svg_time_grid(); |
916 | svg_legenda(); | 921 | svg_legenda(); |
917 | 922 | ||
918 | for (i = 0; i < numcpus; i++) | 923 | for (i = 0; i < numcpus; i++) |
@@ -1127,6 +1132,8 @@ static const struct option options[] = { | |||
1127 | "input file name"), | 1132 | "input file name"), |
1128 | OPT_STRING('o', "output", &output_name, "file", | 1133 | OPT_STRING('o', "output", &output_name, "file", |
1129 | "output file name"), | 1134 | "output file name"), |
1135 | OPT_INTEGER('w', "width", &svg_page_width, | ||
1136 | "page width"), | ||
1130 | OPT_END() | 1137 | OPT_END() |
1131 | }; | 1138 | }; |
1132 | 1139 | ||
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index b0fcecdf378d..a778fd0f4ae4 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
@@ -25,7 +25,8 @@ static u64 turbo_frequency, max_freq; | |||
25 | 25 | ||
26 | #define SLOT_MULT 30.0 | 26 | #define SLOT_MULT 30.0 |
27 | #define SLOT_HEIGHT 25.0 | 27 | #define SLOT_HEIGHT 25.0 |
28 | #define WIDTH 1000.0 | 28 | |
29 | int svg_page_width = 1000; | ||
29 | 30 | ||
30 | #define MIN_TEXT_SIZE 0.001 | 31 | #define MIN_TEXT_SIZE 0.001 |
31 | 32 | ||
@@ -46,21 +47,54 @@ static double time2pixels(u64 time) | |||
46 | { | 47 | { |
47 | double X; | 48 | double X; |
48 | 49 | ||
49 | X = WIDTH * (time - first_time) / (last_time - first_time); | 50 | X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time); |
50 | return X; | 51 | return X; |
51 | } | 52 | } |
52 | 53 | ||
53 | void open_svg(const char *filename, int cpus, int rows) | 54 | /* |
55 | * Round text sizes so that the svg viewer only needs a discrete | ||
56 | * number of renderings of the font | ||
57 | */ | ||
58 | static double round_text_size(double size) | ||
59 | { | ||
60 | int loop = 100; | ||
61 | double target = 10.0; | ||
62 | |||
63 | if (size >= 10.0) | ||
64 | return size; | ||
65 | while (loop--) { | ||
66 | if (size >= target) | ||
67 | return target; | ||
68 | target = target / 2.0; | ||
69 | } | ||
70 | return size; | ||
71 | } | ||
72 | |||
73 | void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) | ||
54 | { | 74 | { |
75 | int new_width; | ||
55 | 76 | ||
56 | svgfile = fopen(filename, "w"); | 77 | svgfile = fopen(filename, "w"); |
57 | if (!svgfile) { | 78 | if (!svgfile) { |
58 | fprintf(stderr, "Cannot open %s for output\n", filename); | 79 | fprintf(stderr, "Cannot open %s for output\n", filename); |
59 | return; | 80 | return; |
60 | } | 81 | } |
82 | first_time = start; | ||
83 | first_time = first_time / 100000000 * 100000000; | ||
84 | last_time = end; | ||
85 | |||
86 | /* | ||
87 | * if the recording is short, we default to a width of 1000, but | ||
88 | * for longer recordings we want at least 200 units of width per second | ||
89 | */ | ||
90 | new_width = (last_time - first_time) / 5000000; | ||
91 | |||
92 | if (new_width > svg_page_width) | ||
93 | svg_page_width = new_width; | ||
94 | |||
61 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; | 95 | total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; |
62 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); | 96 | fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); |
63 | fprintf(svgfile, "<svg width=\"%4.1f\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", WIDTH, total_height); | 97 | fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); |
64 | 98 | ||
65 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); | 99 | fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); |
66 | 100 | ||
@@ -69,7 +103,8 @@ void open_svg(const char *filename, int cpus, int rows) | |||
69 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 103 | fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
70 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 104 | fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
71 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 105 | fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
72 | fprintf(svgfile, " rect.waiting { fill:rgb(255,255, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | 106 | fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); |
107 | fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); | ||
73 | fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n"); | 108 | fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n"); |
74 | fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n"); | 109 | fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n"); |
75 | fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n"); | 110 | fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n"); |
@@ -92,26 +127,78 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type) | |||
92 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); | 127 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); |
93 | } | 128 | } |
94 | 129 | ||
95 | void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type) | 130 | void svg_sample(int Yslot, int cpu, u64 start, u64 end) |
96 | { | 131 | { |
97 | double text_size; | 132 | double text_size; |
98 | if (!svgfile) | 133 | if (!svgfile) |
99 | return; | 134 | return; |
100 | 135 | ||
101 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", | 136 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", |
102 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); | 137 | time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); |
103 | 138 | ||
104 | text_size = (time2pixels(end)-time2pixels(start)); | 139 | text_size = (time2pixels(end)-time2pixels(start)); |
105 | if (cpu > 9) | 140 | if (cpu > 9) |
106 | text_size = text_size/2; | 141 | text_size = text_size/2; |
107 | if (text_size > 1.25) | 142 | if (text_size > 1.25) |
108 | text_size = 1.25; | 143 | text_size = 1.25; |
144 | text_size = round_text_size(text_size); | ||
145 | |||
109 | if (text_size > MIN_TEXT_SIZE) | 146 | if (text_size > MIN_TEXT_SIZE) |
110 | fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%i</text>\n", | 147 | fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", |
111 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); | 148 | time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); |
112 | 149 | ||
113 | } | 150 | } |
114 | 151 | ||
152 | static char *time_to_string(u64 duration) | ||
153 | { | ||
154 | static char text[80]; | ||
155 | |||
156 | text[0] = 0; | ||
157 | |||
158 | if (duration < 1000) /* less than 1 usec */ | ||
159 | return text; | ||
160 | |||
161 | if (duration < 1000 * 1000) { /* less than 1 msec */ | ||
162 | sprintf(text, "%4.1f us", duration / 1000.0); | ||
163 | return text; | ||
164 | } | ||
165 | sprintf(text, "%4.1f ms", duration / 1000.0 / 1000); | ||
166 | |||
167 | return text; | ||
168 | } | ||
169 | |||
170 | void svg_waiting(int Yslot, u64 start, u64 end) | ||
171 | { | ||
172 | char *text; | ||
173 | const char *style; | ||
174 | double font_size; | ||
175 | |||
176 | if (!svgfile) | ||
177 | return; | ||
178 | |||
179 | style = "waiting"; | ||
180 | |||
181 | if (end-start > 10 * 1000000) /* 10 msec */ | ||
182 | style = "WAITING"; | ||
183 | |||
184 | text = time_to_string(end-start); | ||
185 | |||
186 | font_size = 1.0 * (time2pixels(end)-time2pixels(start)); | ||
187 | |||
188 | if (font_size > 3) | ||
189 | font_size = 3; | ||
190 | |||
191 | font_size = round_text_size(font_size); | ||
192 | |||
193 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); | ||
194 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | ||
195 | time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); | ||
196 | if (font_size > MIN_TEXT_SIZE) | ||
197 | fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n", | ||
198 | font_size, text); | ||
199 | fprintf(svgfile, "</g>\n"); | ||
200 | } | ||
201 | |||
115 | static char *cpu_model(void) | 202 | static char *cpu_model(void) |
116 | { | 203 | { |
117 | static char cpu_m[255]; | 204 | static char cpu_m[255]; |
@@ -148,7 +235,7 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) | |||
148 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); | 235 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); |
149 | 236 | ||
150 | sprintf(cpu_string, "CPU %i", (int)cpu+1); | 237 | sprintf(cpu_string, "CPU %i", (int)cpu+1); |
151 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n", | 238 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", |
152 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); | 239 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); |
153 | 240 | ||
154 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", | 241 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", |
@@ -162,15 +249,21 @@ void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name | |||
162 | if (!svgfile) | 249 | if (!svgfile) |
163 | return; | 250 | return; |
164 | 251 | ||
165 | fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", | 252 | |
166 | time2pixels(start), time2pixels(end)-time2pixels(start), cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT, type); | 253 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); |
254 | fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | ||
255 | time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); | ||
167 | width = time2pixels(end)-time2pixels(start); | 256 | width = time2pixels(end)-time2pixels(start); |
168 | if (width > 6) | 257 | if (width > 6) |
169 | width = 6; | 258 | width = 6; |
170 | 259 | ||
260 | width = round_text_size(width); | ||
261 | |||
171 | if (width > MIN_TEXT_SIZE) | 262 | if (width > MIN_TEXT_SIZE) |
172 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">%s</text>\n", | 263 | fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n", |
173 | time2pixels(start), cpu2y(cpu), width, name); | 264 | width, name); |
265 | |||
266 | fprintf(svgfile, "</g>\n"); | ||
174 | } | 267 | } |
175 | 268 | ||
176 | void svg_cstate(int cpu, u64 start, u64 end, int type) | 269 | void svg_cstate(int cpu, u64 start, u64 end, int type) |
@@ -191,13 +284,15 @@ void svg_cstate(int cpu, u64 start, u64 end, int type) | |||
191 | time2pixels(start), time2pixels(end)-time2pixels(start), | 284 | time2pixels(start), time2pixels(end)-time2pixels(start), |
192 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); | 285 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); |
193 | 286 | ||
194 | width = time2pixels(end)-time2pixels(start); | 287 | width = (time2pixels(end)-time2pixels(start))/2.0; |
195 | if (width > 6) | 288 | if (width > 6) |
196 | width = 6; | 289 | width = 6; |
197 | 290 | ||
291 | width = round_text_size(width); | ||
292 | |||
198 | if (width > MIN_TEXT_SIZE) | 293 | if (width > MIN_TEXT_SIZE) |
199 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">C%i</text>\n", | 294 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", |
200 | time2pixels(start), cpu2y(cpu), width, type); | 295 | time2pixels(start), cpu2y(cpu)+width, width, type); |
201 | } | 296 | } |
202 | 297 | ||
203 | static char *HzToHuman(unsigned long hz) | 298 | static char *HzToHuman(unsigned long hz) |
@@ -236,13 +331,13 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq) | |||
236 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; | 331 | height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; |
237 | fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n", | 332 | fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n", |
238 | time2pixels(start), time2pixels(end), height, height); | 333 | time2pixels(start), time2pixels(end), height, height); |
239 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"0.25pt\">%s</text>\n", | 334 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", |
240 | time2pixels(start), height+0.9, HzToHuman(freq)); | 335 | time2pixels(start), height+0.9, HzToHuman(freq)); |
241 | 336 | ||
242 | } | 337 | } |
243 | 338 | ||
244 | 339 | ||
245 | void svg_partial_wakeline(u64 start, int row1, int row2) | 340 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) |
246 | { | 341 | { |
247 | double height; | 342 | double height; |
248 | 343 | ||
@@ -251,21 +346,35 @@ void svg_partial_wakeline(u64 start, int row1, int row2) | |||
251 | 346 | ||
252 | 347 | ||
253 | if (row1 < row2) { | 348 | if (row1 < row2) { |
254 | if (row1) | 349 | if (row1) { |
255 | 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", | 350 | 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", |
256 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); | 351 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); |
257 | 352 | if (desc2) | |
258 | if (row2) | 353 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n", |
354 | time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2); | ||
355 | } | ||
356 | if (row2) { | ||
259 | 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", | 357 | 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", |
260 | time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT); | 358 | time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT); |
359 | if (desc1) | ||
360 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n", | ||
361 | time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1); | ||
362 | } | ||
261 | } else { | 363 | } else { |
262 | if (row2) | 364 | if (row2) { |
263 | 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", | 365 | 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", |
264 | time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); | 366 | time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); |
265 | 367 | if (desc1) | |
266 | if (row1) | 368 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n", |
369 | time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1); | ||
370 | } | ||
371 | if (row1) { | ||
267 | 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", | 372 | 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", |
268 | time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT); | 373 | time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT); |
374 | if (desc2) | ||
375 | fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n", | ||
376 | time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2); | ||
377 | } | ||
269 | } | 378 | } |
270 | height = row1 * SLOT_MULT; | 379 | height = row1 * SLOT_MULT; |
271 | if (row2 > row1) | 380 | if (row2 > row1) |
@@ -313,7 +422,7 @@ void svg_text(int Yslot, u64 start, const char *text) | |||
313 | if (!svgfile) | 422 | if (!svgfile) |
314 | return; | 423 | return; |
315 | 424 | ||
316 | fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n", | 425 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", |
317 | time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text); | 426 | time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text); |
318 | } | 427 | } |
319 | 428 | ||
@@ -324,7 +433,7 @@ static void svg_legenda_box(int X, const char *text, const char *style) | |||
324 | 433 | ||
325 | fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", | 434 | fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", |
326 | X, boxsize, boxsize, style); | 435 | X, boxsize, boxsize, style); |
327 | fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.4fpt\">%s</text>\n", | 436 | fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n", |
328 | X + boxsize + 5, boxsize, 0.8 * boxsize, text); | 437 | X + boxsize + 5, boxsize, 0.8 * boxsize, text); |
329 | } | 438 | } |
330 | 439 | ||
@@ -342,15 +451,10 @@ void svg_legenda(void) | |||
342 | svg_legenda_box(800, "Blocked on IO", "blocked"); | 451 | svg_legenda_box(800, "Blocked on IO", "blocked"); |
343 | } | 452 | } |
344 | 453 | ||
345 | void svg_time_grid(u64 start, u64 end) | 454 | void svg_time_grid(void) |
346 | { | 455 | { |
347 | u64 i; | 456 | u64 i; |
348 | 457 | ||
349 | first_time = start; | ||
350 | last_time = end; | ||
351 | |||
352 | first_time = first_time / 100000000 * 100000000; | ||
353 | |||
354 | if (!svgfile) | 458 | if (!svgfile) |
355 | return; | 459 | return; |
356 | 460 | ||
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h index ad79b5dc53de..cd93195aedb3 100644 --- a/tools/perf/util/svghelper.h +++ b/tools/perf/util/svghelper.h | |||
@@ -3,9 +3,10 @@ | |||
3 | 3 | ||
4 | #include "types.h" | 4 | #include "types.h" |
5 | 5 | ||
6 | extern void open_svg(const char *filename, int cpus, int rows); | 6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); |
7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); | 7 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); |
8 | extern void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type); | 8 | extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); |
9 | extern void svg_waiting(int Yslot, u64 start, u64 end); | ||
9 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); | 10 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); |
10 | 11 | ||
11 | 12 | ||
@@ -14,12 +15,14 @@ extern void svg_cstate(int cpu, u64 start, u64 end, int type); | |||
14 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); | 15 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); |
15 | 16 | ||
16 | 17 | ||
17 | extern void svg_time_grid(u64 start, u64 end); | 18 | extern void svg_time_grid(void); |
18 | extern void svg_legenda(void); | 19 | extern void svg_legenda(void); |
19 | extern void svg_wakeline(u64 start, int row1, int row2); | 20 | extern void svg_wakeline(u64 start, int row1, int row2); |
20 | extern void svg_partial_wakeline(u64 start, int row1, int row2); | 21 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); |
21 | extern void svg_interrupt(u64 start, int row); | 22 | extern void svg_interrupt(u64 start, int row); |
22 | extern void svg_text(int Yslot, u64 start, const char *text); | 23 | extern void svg_text(int Yslot, u64 start, const char *text); |
23 | extern void svg_close(void); | 24 | extern void svg_close(void); |
24 | 25 | ||
26 | extern int svg_page_width; | ||
27 | |||
25 | #endif | 28 | #endif |