diff options
author | Jiri Olsa <jolsa@kernel.org> | 2014-05-23 11:15:47 -0400 |
---|---|---|
committer | Jiri Olsa <jolsa@kernel.org> | 2014-06-03 15:34:59 -0400 |
commit | f29984226978313039d7dfe9b45eaa55a3aad03d (patch) | |
tree | 63ddd8b0f5ad2c748a5b419c44b2eb70af906d68 /tools | |
parent | 2ec85c628c4cecef0f82d177279c579aed0f9706 (diff) |
perf tools: Move elide bool into perf_hpp_fmt struct
After output/sort fields refactoring, it's expensive
to check the elide bool in its current location inside
the 'struct sort_entry'.
The perf_hpp__should_skip function gets highly noticable in
workloads with high number of output/sort fields, like for:
$ perf report -i perf-test.data -F overhead,sample,period,comm,pid,dso,symbol,cpu --stdio
Performance report:
9.70% perf [.] perf_hpp__should_skip
Moving the elide bool into the 'struct perf_hpp_fmt', which
makes the perf_hpp__should_skip just single struct read.
Got speedup of around 22% for my test perf.data workload.
The change should not harm any other workload types.
Performance counter stats for (10 runs):
before:
358,319,732,626 cycles ( +- 0.55% )
467,129,581,515 instructions # 1.30 insns per cycle ( +- 0.00% )
150.943975206 seconds time elapsed ( +- 0.62% )
now:
278,785,972,990 cycles ( +- 0.12% )
370,146,797,640 instructions # 1.33 insns per cycle ( +- 0.00% )
116.416670507 seconds time elapsed ( +- 0.31% )
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/20140601142622.GA9131@krava.brq.redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 8 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 8 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 90 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 2 |
4 files changed, 68 insertions, 40 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 5905acde5f1d..52c03fbbba17 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -1706,14 +1706,14 @@ zoom_dso: | |||
1706 | zoom_out_dso: | 1706 | zoom_out_dso: |
1707 | ui_helpline__pop(); | 1707 | ui_helpline__pop(); |
1708 | browser->hists->dso_filter = NULL; | 1708 | browser->hists->dso_filter = NULL; |
1709 | sort_dso.elide = false; | 1709 | perf_hpp__set_elide(HISTC_DSO, false); |
1710 | } else { | 1710 | } else { |
1711 | if (dso == NULL) | 1711 | if (dso == NULL) |
1712 | continue; | 1712 | continue; |
1713 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", | 1713 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", |
1714 | dso->kernel ? "the Kernel" : dso->short_name); | 1714 | dso->kernel ? "the Kernel" : dso->short_name); |
1715 | browser->hists->dso_filter = dso; | 1715 | browser->hists->dso_filter = dso; |
1716 | sort_dso.elide = true; | 1716 | perf_hpp__set_elide(HISTC_DSO, true); |
1717 | pstack__push(fstack, &browser->hists->dso_filter); | 1717 | pstack__push(fstack, &browser->hists->dso_filter); |
1718 | } | 1718 | } |
1719 | hists__filter_by_dso(hists); | 1719 | hists__filter_by_dso(hists); |
@@ -1725,13 +1725,13 @@ zoom_thread: | |||
1725 | zoom_out_thread: | 1725 | zoom_out_thread: |
1726 | ui_helpline__pop(); | 1726 | ui_helpline__pop(); |
1727 | browser->hists->thread_filter = NULL; | 1727 | browser->hists->thread_filter = NULL; |
1728 | sort_thread.elide = false; | 1728 | perf_hpp__set_elide(HISTC_THREAD, false); |
1729 | } else { | 1729 | } else { |
1730 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", | 1730 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", |
1731 | thread->comm_set ? thread__comm_str(thread) : "", | 1731 | thread->comm_set ? thread__comm_str(thread) : "", |
1732 | thread->tid); | 1732 | thread->tid); |
1733 | browser->hists->thread_filter = thread; | 1733 | browser->hists->thread_filter = thread; |
1734 | sort_thread.elide = true; | 1734 | perf_hpp__set_elide(HISTC_THREAD, false); |
1735 | pstack__push(fstack, &browser->hists->thread_filter); | 1735 | pstack__push(fstack, &browser->hists->thread_filter); |
1736 | } | 1736 | } |
1737 | hists__filter_by_thread(hists); | 1737 | hists__filter_by_thread(hists); |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 82b28ff98062..d2bf03575d5f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -205,6 +205,7 @@ struct perf_hpp_fmt { | |||
205 | 205 | ||
206 | struct list_head list; | 206 | struct list_head list; |
207 | struct list_head sort_list; | 207 | struct list_head sort_list; |
208 | bool elide; | ||
208 | }; | 209 | }; |
209 | 210 | ||
210 | extern struct list_head perf_hpp__list; | 211 | extern struct list_head perf_hpp__list; |
@@ -252,7 +253,12 @@ void perf_hpp__append_sort_keys(void); | |||
252 | 253 | ||
253 | bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); | 254 | bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); |
254 | bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); | 255 | bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); |
255 | bool perf_hpp__should_skip(struct perf_hpp_fmt *format); | 256 | |
257 | static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format) | ||
258 | { | ||
259 | return format->elide; | ||
260 | } | ||
261 | |||
256 | void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); | 262 | void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); |
257 | 263 | ||
258 | typedef u64 (*hpp_field_fn)(struct hist_entry *he); | 264 | typedef u64 (*hpp_field_fn)(struct hist_entry *he); |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 2aba620a86f6..45512baaab67 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -1157,6 +1157,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) | |||
1157 | 1157 | ||
1158 | INIT_LIST_HEAD(&hse->hpp.list); | 1158 | INIT_LIST_HEAD(&hse->hpp.list); |
1159 | INIT_LIST_HEAD(&hse->hpp.sort_list); | 1159 | INIT_LIST_HEAD(&hse->hpp.sort_list); |
1160 | hse->hpp.elide = false; | ||
1160 | 1161 | ||
1161 | return hse; | 1162 | return hse; |
1162 | } | 1163 | } |
@@ -1364,27 +1365,64 @@ static int __setup_sorting(void) | |||
1364 | return ret; | 1365 | return ret; |
1365 | } | 1366 | } |
1366 | 1367 | ||
1367 | bool perf_hpp__should_skip(struct perf_hpp_fmt *format) | 1368 | void perf_hpp__set_elide(int idx, bool elide) |
1368 | { | 1369 | { |
1369 | if (perf_hpp__is_sort_entry(format)) { | 1370 | struct perf_hpp_fmt *fmt; |
1370 | struct hpp_sort_entry *hse; | 1371 | struct hpp_sort_entry *hse; |
1371 | 1372 | ||
1372 | hse = container_of(format, struct hpp_sort_entry, hpp); | 1373 | perf_hpp__for_each_format(fmt) { |
1373 | return hse->se->elide; | 1374 | if (!perf_hpp__is_sort_entry(fmt)) |
1375 | continue; | ||
1376 | |||
1377 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | ||
1378 | if (hse->se->se_width_idx == idx) { | ||
1379 | fmt->elide = elide; | ||
1380 | break; | ||
1381 | } | ||
1374 | } | 1382 | } |
1375 | return false; | ||
1376 | } | 1383 | } |
1377 | 1384 | ||
1378 | static void sort_entry__setup_elide(struct sort_entry *se, | 1385 | static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp) |
1379 | struct strlist *list, | ||
1380 | const char *list_name, FILE *fp) | ||
1381 | { | 1386 | { |
1382 | if (list && strlist__nr_entries(list) == 1) { | 1387 | if (list && strlist__nr_entries(list) == 1) { |
1383 | if (fp != NULL) | 1388 | if (fp != NULL) |
1384 | fprintf(fp, "# %s: %s\n", list_name, | 1389 | fprintf(fp, "# %s: %s\n", list_name, |
1385 | strlist__entry(list, 0)->s); | 1390 | strlist__entry(list, 0)->s); |
1386 | se->elide = true; | 1391 | return true; |
1392 | } | ||
1393 | return false; | ||
1394 | } | ||
1395 | |||
1396 | static bool get_elide(int idx, FILE *output) | ||
1397 | { | ||
1398 | switch (idx) { | ||
1399 | case HISTC_SYMBOL: | ||
1400 | return __get_elide(symbol_conf.sym_list, "symbol", output); | ||
1401 | case HISTC_DSO: | ||
1402 | return __get_elide(symbol_conf.dso_list, "dso", output); | ||
1403 | case HISTC_COMM: | ||
1404 | return __get_elide(symbol_conf.comm_list, "comm", output); | ||
1405 | default: | ||
1406 | break; | ||
1387 | } | 1407 | } |
1408 | |||
1409 | if (sort__mode != SORT_MODE__BRANCH) | ||
1410 | return false; | ||
1411 | |||
1412 | switch (idx) { | ||
1413 | case HISTC_SYMBOL_FROM: | ||
1414 | return __get_elide(symbol_conf.sym_from_list, "sym_from", output); | ||
1415 | case HISTC_SYMBOL_TO: | ||
1416 | return __get_elide(symbol_conf.sym_to_list, "sym_to", output); | ||
1417 | case HISTC_DSO_FROM: | ||
1418 | return __get_elide(symbol_conf.dso_from_list, "dso_from", output); | ||
1419 | case HISTC_DSO_TO: | ||
1420 | return __get_elide(symbol_conf.dso_to_list, "dso_to", output); | ||
1421 | default: | ||
1422 | break; | ||
1423 | } | ||
1424 | |||
1425 | return false; | ||
1388 | } | 1426 | } |
1389 | 1427 | ||
1390 | void sort__setup_elide(FILE *output) | 1428 | void sort__setup_elide(FILE *output) |
@@ -1392,26 +1430,12 @@ void sort__setup_elide(FILE *output) | |||
1392 | struct perf_hpp_fmt *fmt; | 1430 | struct perf_hpp_fmt *fmt; |
1393 | struct hpp_sort_entry *hse; | 1431 | struct hpp_sort_entry *hse; |
1394 | 1432 | ||
1395 | sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, | 1433 | perf_hpp__for_each_format(fmt) { |
1396 | "dso", output); | 1434 | if (!perf_hpp__is_sort_entry(fmt)) |
1397 | sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, | 1435 | continue; |
1398 | "comm", output); | 1436 | |
1399 | sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, | 1437 | hse = container_of(fmt, struct hpp_sort_entry, hpp); |
1400 | "symbol", output); | 1438 | fmt->elide = get_elide(hse->se->se_width_idx, output); |
1401 | |||
1402 | if (sort__mode == SORT_MODE__BRANCH) { | ||
1403 | sort_entry__setup_elide(&sort_dso_from, | ||
1404 | symbol_conf.dso_from_list, | ||
1405 | "dso_from", output); | ||
1406 | sort_entry__setup_elide(&sort_dso_to, | ||
1407 | symbol_conf.dso_to_list, | ||
1408 | "dso_to", output); | ||
1409 | sort_entry__setup_elide(&sort_sym_from, | ||
1410 | symbol_conf.sym_from_list, | ||
1411 | "sym_from", output); | ||
1412 | sort_entry__setup_elide(&sort_sym_to, | ||
1413 | symbol_conf.sym_to_list, | ||
1414 | "sym_to", output); | ||
1415 | } | 1439 | } |
1416 | 1440 | ||
1417 | /* | 1441 | /* |
@@ -1422,8 +1446,7 @@ void sort__setup_elide(FILE *output) | |||
1422 | if (!perf_hpp__is_sort_entry(fmt)) | 1446 | if (!perf_hpp__is_sort_entry(fmt)) |
1423 | continue; | 1447 | continue; |
1424 | 1448 | ||
1425 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | 1449 | if (!fmt->elide) |
1426 | if (!hse->se->elide) | ||
1427 | return; | 1450 | return; |
1428 | } | 1451 | } |
1429 | 1452 | ||
@@ -1431,8 +1454,7 @@ void sort__setup_elide(FILE *output) | |||
1431 | if (!perf_hpp__is_sort_entry(fmt)) | 1454 | if (!perf_hpp__is_sort_entry(fmt)) |
1432 | continue; | 1455 | continue; |
1433 | 1456 | ||
1434 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | 1457 | fmt->elide = false; |
1435 | hse->se->elide = false; | ||
1436 | } | 1458 | } |
1437 | } | 1459 | } |
1438 | 1460 | ||
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 426b873e16ff..5bf0098d6b06 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -202,7 +202,6 @@ struct sort_entry { | |||
202 | int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size, | 202 | int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size, |
203 | unsigned int width); | 203 | unsigned int width); |
204 | u8 se_width_idx; | 204 | u8 se_width_idx; |
205 | bool elide; | ||
206 | }; | 205 | }; |
207 | 206 | ||
208 | extern struct sort_entry sort_thread; | 207 | extern struct sort_entry sort_thread; |
@@ -213,6 +212,7 @@ int setup_output_field(void); | |||
213 | void reset_output_field(void); | 212 | void reset_output_field(void); |
214 | extern int sort_dimension__add(const char *); | 213 | extern int sort_dimension__add(const char *); |
215 | void sort__setup_elide(FILE *fp); | 214 | void sort__setup_elide(FILE *fp); |
215 | void perf_hpp__set_elide(int idx, bool elide); | ||
216 | 216 | ||
217 | int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); | 217 | int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); |
218 | 218 | ||