diff options
author | Lin Ming <ming.m.lin@intel.com> | 2011-03-25 04:27:48 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-03-29 12:40:27 -0400 |
commit | cd25f8bc2696664877b21d33b7994e12fa570919 (patch) | |
tree | 13c56bdc4f248d76804fc703a44b79887cfba159 /tools | |
parent | ca6a42586fae639ff9e5285d9bdc550fcb1b8d41 (diff) |
perf probe: Add fastpath to do lookup by function name
v3 -> v2:
- Make pubname_search_cb more generic
- Add fastpath to find_probes also
v2 -> v1:
- Don't compare file names with cu_find_realpath(...), instead, compare
them with the name returned by dwarf_decl_file(sp_die)
The vmlinux file may have thousands of CUs.
We can lookup function name from .debug_pubnames section
to avoid the slow loop on CUs.
1. Improvement data for find_line_range
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--line csum_partial_copy_to_user > tmp.log
before patch applied
=====================
847,988,276 cycles
0.355075856 seconds time elapsed
after patch applied
=====================
206,102,622 cycles
0.086883555 seconds time elapsed
2. Improvement data for find_probes
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--vars csum_partial_copy_to_user > tmp.log
before patch applied
=====================
848,490,844 cycles
0.355307901 seconds time elapsed
after patch applied
=====================
205,684,469 cycles
0.086694010 seconds time elapsed
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: linux-kernel <linux-kernel@vger.kernel.org>
LKML-Reference: <1301041668.14111.52.camel@minggr.sh.intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/probe-finder.c | 72 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 2 |
2 files changed, 74 insertions, 0 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 194f9e2a3285..ff416b85f7e8 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1435,6 +1435,38 @@ static int find_probe_point_by_func(struct probe_finder *pf) | |||
1435 | return _param.retval; | 1435 | return _param.retval; |
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | struct pubname_callback_param { | ||
1439 | char *function; | ||
1440 | char *file; | ||
1441 | Dwarf_Die *cu_die; | ||
1442 | Dwarf_Die *sp_die; | ||
1443 | int found; | ||
1444 | }; | ||
1445 | |||
1446 | static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) | ||
1447 | { | ||
1448 | struct pubname_callback_param *param = data; | ||
1449 | |||
1450 | if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { | ||
1451 | if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) | ||
1452 | return DWARF_CB_OK; | ||
1453 | |||
1454 | if (die_compare_name(param->sp_die, param->function)) { | ||
1455 | if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) | ||
1456 | return DWARF_CB_OK; | ||
1457 | |||
1458 | if (param->file && | ||
1459 | strtailcmp(param->file, dwarf_decl_file(param->sp_die))) | ||
1460 | return DWARF_CB_OK; | ||
1461 | |||
1462 | param->found = 1; | ||
1463 | return DWARF_CB_ABORT; | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | return DWARF_CB_OK; | ||
1468 | } | ||
1469 | |||
1438 | /* Find probe points from debuginfo */ | 1470 | /* Find probe points from debuginfo */ |
1439 | static int find_probes(int fd, struct probe_finder *pf) | 1471 | static int find_probes(int fd, struct probe_finder *pf) |
1440 | { | 1472 | { |
@@ -1461,6 +1493,27 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
1461 | 1493 | ||
1462 | off = 0; | 1494 | off = 0; |
1463 | line_list__init(&pf->lcache); | 1495 | line_list__init(&pf->lcache); |
1496 | |||
1497 | /* Fastpath: lookup by function name from .debug_pubnames section */ | ||
1498 | if (pp->function) { | ||
1499 | struct pubname_callback_param pubname_param = { | ||
1500 | .function = pp->function, | ||
1501 | .file = pp->file, | ||
1502 | .cu_die = &pf->cu_die, | ||
1503 | .sp_die = &pf->sp_die, | ||
1504 | }; | ||
1505 | struct dwarf_callback_param probe_param = { | ||
1506 | .data = pf, | ||
1507 | }; | ||
1508 | |||
1509 | dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | ||
1510 | if (pubname_param.found) { | ||
1511 | ret = probe_point_search_cb(&pf->sp_die, &probe_param); | ||
1512 | if (ret) | ||
1513 | goto found; | ||
1514 | } | ||
1515 | } | ||
1516 | |||
1464 | /* Loop on CUs (Compilation Unit) */ | 1517 | /* Loop on CUs (Compilation Unit) */ |
1465 | while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { | 1518 | while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { |
1466 | /* Get the DIE(Debugging Information Entry) of this CU */ | 1519 | /* Get the DIE(Debugging Information Entry) of this CU */ |
@@ -1488,6 +1541,8 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
1488 | } | 1541 | } |
1489 | off = noff; | 1542 | off = noff; |
1490 | } | 1543 | } |
1544 | |||
1545 | found: | ||
1491 | line_list__free(&pf->lcache); | 1546 | line_list__free(&pf->lcache); |
1492 | if (dwfl) | 1547 | if (dwfl) |
1493 | dwfl_end(dwfl); | 1548 | dwfl_end(dwfl); |
@@ -1895,6 +1950,22 @@ int find_line_range(int fd, struct line_range *lr) | |||
1895 | return -EBADF; | 1950 | return -EBADF; |
1896 | } | 1951 | } |
1897 | 1952 | ||
1953 | /* Fastpath: lookup by function name from .debug_pubnames section */ | ||
1954 | if (lr->function) { | ||
1955 | struct pubname_callback_param pubname_param = { | ||
1956 | .function = lr->function, .file = lr->file, | ||
1957 | .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; | ||
1958 | struct dwarf_callback_param line_range_param = { | ||
1959 | .data = (void *)&lf, .retval = 0}; | ||
1960 | |||
1961 | dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); | ||
1962 | if (pubname_param.found) { | ||
1963 | line_range_search_cb(&lf.sp_die, &line_range_param); | ||
1964 | if (lf.found) | ||
1965 | goto found; | ||
1966 | } | ||
1967 | } | ||
1968 | |||
1898 | /* Loop on CUs (Compilation Unit) */ | 1969 | /* Loop on CUs (Compilation Unit) */ |
1899 | while (!lf.found && ret >= 0) { | 1970 | while (!lf.found && ret >= 0) { |
1900 | if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) | 1971 | if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) |
@@ -1923,6 +1994,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
1923 | off = noff; | 1994 | off = noff; |
1924 | } | 1995 | } |
1925 | 1996 | ||
1997 | found: | ||
1926 | /* Store comp_dir */ | 1998 | /* Store comp_dir */ |
1927 | if (lf.found) { | 1999 | if (lf.found) { |
1928 | comp_dir = cu_get_comp_dir(&lf.cu_die); | 2000 | comp_dir = cu_get_comp_dir(&lf.cu_die); |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index beaefc3c1223..605730a366db 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -49,6 +49,7 @@ struct probe_finder { | |||
49 | Dwarf_Addr addr; /* Address */ | 49 | Dwarf_Addr addr; /* Address */ |
50 | const char *fname; /* Real file name */ | 50 | const char *fname; /* Real file name */ |
51 | Dwarf_Die cu_die; /* Current CU */ | 51 | Dwarf_Die cu_die; /* Current CU */ |
52 | Dwarf_Die sp_die; | ||
52 | struct list_head lcache; /* Line cache for lazy match */ | 53 | struct list_head lcache; /* Line cache for lazy match */ |
53 | 54 | ||
54 | /* For variable searching */ | 55 | /* For variable searching */ |
@@ -83,6 +84,7 @@ struct line_finder { | |||
83 | int lno_s; /* Start line number */ | 84 | int lno_s; /* Start line number */ |
84 | int lno_e; /* End line number */ | 85 | int lno_e; /* End line number */ |
85 | Dwarf_Die cu_die; /* Current CU */ | 86 | Dwarf_Die cu_die; /* Current CU */ |
87 | Dwarf_Die sp_die; | ||
86 | int found; | 88 | int found; |
87 | }; | 89 | }; |
88 | 90 | ||