aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2011-03-25 04:27:48 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-03-29 12:40:27 -0400
commitcd25f8bc2696664877b21d33b7994e12fa570919 (patch)
tree13c56bdc4f248d76804fc703a44b79887cfba159 /tools
parentca6a42586fae639ff9e5285d9bdc550fcb1b8d41 (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.c72
-rw-r--r--tools/perf/util/probe-finder.h2
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
1438struct pubname_callback_param {
1439 char *function;
1440 char *file;
1441 Dwarf_Die *cu_die;
1442 Dwarf_Die *sp_die;
1443 int found;
1444};
1445
1446static 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 */
1439static int find_probes(int fd, struct probe_finder *pf) 1471static 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
1545found:
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
1997found:
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