aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-timechart.c
diff options
context:
space:
mode:
authorStanislav Fomichev <stfomichev@yandex-team.ru>2014-07-08 12:03:43 -0400
committerJiri Olsa <jolsa@kernel.org>2014-07-09 18:22:54 -0400
commitd243144af0b52fc5164a0823194f29a5979e236c (patch)
tree85dbbc2db11764cebf06856246884c9b60834dc5 /tools/perf/builtin-timechart.c
parent962e310af5dff432745ae7494096ed54b752e63e (diff)
perf timechart: Add more options to IO mode
--io-skip-eagain - don't show EAGAIN errors --io-min-time - make small io bursts visible --io-merge-dist - merge adjacent events Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru> Acked-by: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/n/1404835423-23098-5-git-send-email-stfomichev@yandex-team.ru Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools/perf/builtin-timechart.c')
-rw-r--r--tools/perf/builtin-timechart.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 37bf1eb0755f..04c9c53becad 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -62,7 +62,10 @@ struct timechart {
62 topology; 62 topology;
63 /* IO related settings */ 63 /* IO related settings */
64 u64 io_events; 64 u64 io_events;
65 bool io_only; 65 bool io_only,
66 skip_eagain;
67 u64 min_time,
68 merge_dist;
66}; 69};
67 70
68struct per_pidcomm; 71struct per_pidcomm;
@@ -761,7 +764,7 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
761{ 764{
762 struct per_pid *p = find_create_pid(tchart, pid); 765 struct per_pid *p = find_create_pid(tchart, pid);
763 struct per_pidcomm *c = p->current; 766 struct per_pidcomm *c = p->current;
764 struct io_sample *sample; 767 struct io_sample *sample, *prev;
765 768
766 if (!c) { 769 if (!c) {
767 pr_warning("Invalid pidcomm!\n"); 770 pr_warning("Invalid pidcomm!\n");
@@ -785,6 +788,18 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
785 } 788 }
786 789
787 sample->end_time = end; 790 sample->end_time = end;
791 prev = sample->next;
792
793 /* we want to be able to see small and fast transfers, so make them
794 * at least min_time long, but don't overlap them */
795 if (sample->end_time - sample->start_time < tchart->min_time)
796 sample->end_time = sample->start_time + tchart->min_time;
797 if (prev && sample->start_time < prev->end_time) {
798 if (prev->err) /* try to make errors more visible */
799 sample->start_time = prev->end_time;
800 else
801 prev->end_time = sample->start_time;
802 }
788 803
789 if (ret < 0) { 804 if (ret < 0) {
790 sample->err = ret; 805 sample->err = ret;
@@ -799,6 +814,24 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
799 sample->bytes = ret; 814 sample->bytes = ret;
800 } 815 }
801 816
817 /* merge two requests to make svg smaller and render-friendly */
818 if (prev &&
819 prev->type == sample->type &&
820 prev->err == sample->err &&
821 prev->fd == sample->fd &&
822 prev->end_time + tchart->merge_dist >= sample->start_time) {
823
824 sample->bytes += prev->bytes;
825 sample->merges += prev->merges + 1;
826
827 sample->start_time = prev->start_time;
828 sample->next = prev->next;
829 free(prev);
830
831 if (!sample->err && sample->bytes > c->max_bytes)
832 c->max_bytes = sample->bytes;
833 }
834
802 tchart->io_events++; 835 tchart->io_events++;
803 836
804 return 0; 837 return 0;
@@ -1119,6 +1152,10 @@ static void draw_io_bars(struct timechart *tchart)
1119 for (sample = c->io_samples; sample; sample = sample->next) { 1152 for (sample = c->io_samples; sample; sample = sample->next) {
1120 double h = (double)sample->bytes / c->max_bytes; 1153 double h = (double)sample->bytes / c->max_bytes;
1121 1154
1155 if (tchart->skip_eagain &&
1156 sample->err == -EAGAIN)
1157 continue;
1158
1122 if (sample->err) 1159 if (sample->err)
1123 h = 1; 1160 h = 1;
1124 1161
@@ -1849,6 +1886,30 @@ parse_highlight(const struct option *opt __maybe_unused, const char *arg,
1849 return 0; 1886 return 0;
1850} 1887}
1851 1888
1889static int
1890parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
1891{
1892 char unit = 'n';
1893 u64 *value = opt->value;
1894
1895 if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) {
1896 switch (unit) {
1897 case 'm':
1898 *value *= 1000000;
1899 break;
1900 case 'u':
1901 *value *= 1000;
1902 break;
1903 case 'n':
1904 break;
1905 default:
1906 return -1;
1907 }
1908 }
1909
1910 return 0;
1911}
1912
1852int cmd_timechart(int argc, const char **argv, 1913int cmd_timechart(int argc, const char **argv,
1853 const char *prefix __maybe_unused) 1914 const char *prefix __maybe_unused)
1854{ 1915{
@@ -1861,6 +1922,8 @@ int cmd_timechart(int argc, const char **argv,
1861 .ordered_samples = true, 1922 .ordered_samples = true,
1862 }, 1923 },
1863 .proc_num = 15, 1924 .proc_num = 15,
1925 .min_time = 1000000,
1926 .merge_dist = 1000,
1864 }; 1927 };
1865 const char *output_name = "output.svg"; 1928 const char *output_name = "output.svg";
1866 const struct option timechart_options[] = { 1929 const struct option timechart_options[] = {
@@ -1882,6 +1945,14 @@ int cmd_timechart(int argc, const char **argv,
1882 "min. number of tasks to print"), 1945 "min. number of tasks to print"),
1883 OPT_BOOLEAN('t', "topology", &tchart.topology, 1946 OPT_BOOLEAN('t', "topology", &tchart.topology,
1884 "sort CPUs according to topology"), 1947 "sort CPUs according to topology"),
1948 OPT_BOOLEAN(0, "io-skip-eagain", &tchart.skip_eagain,
1949 "skip EAGAIN errors"),
1950 OPT_CALLBACK(0, "io-min-time", &tchart.min_time, "time",
1951 "all IO faster than min-time will visually appear longer",
1952 parse_time),
1953 OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
1954 "merge events that are merge-dist us apart",
1955 parse_time),
1885 OPT_END() 1956 OPT_END()
1886 }; 1957 };
1887 const char * const timechart_usage[] = { 1958 const char * const timechart_usage[] = {