diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2019-05-20 07:37:26 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-06-05 08:47:57 -0400 |
commit | 38a846d47f3d2fe6783e2df7bc5c2415239e6a63 (patch) | |
tree | 21c0c8f4dcfb71cbab3e121cfc4e49cb28a30160 /tools/perf/scripts/python/exported-sql-viewer.py | |
parent | 4a0979d4b4feee67a7f9a5605b5bfae3b0a2b6a9 (diff) |
perf scripts python: exported-sql-viewer.py: Add IPC information to Call Graph Graph
Enhance the call graph to display IPC information if it is available.
Committer testing:
[acme@quaco adrian.hunter]$ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py ~/c/adrian.hunter/simple-retpoline.db
Reports -> Context Sensitive Callgraph, then expand a few trees, then
select with the mouse and press control+C:
Call Path Object Count Time(ns) Time(%) Insn Insn Cyc Cyc IPC Branch Branch
▼ simple-retpolin Cnt Cnt(%) Cnt Cnt(%) Cnt Cnt(%)
▼ 23003:23003
▼ _start ld-2.28.so 1 218295 100.0 127746 100.0 207320 100.0 0.62 13046 100.0
▶ unknown unknown 1 3202 1.5 0 0.0 0 0.0 0 1 0.0
▶ _dl_start ld-2.28.so 1 188471 86.3 123394 96.6 180007 86.8 0.69 12529 96.0
▶ _dl_init ld-2.28.so 1 13406 6.1 3207 2.5 14868 7.2 0.22 327 2.5
▼ _start simple-retpoline 1 12899 5.9 1142 0.9 11561 5.6 0.10 184 1.4
▶ unknown unknown 1 846 6.6 0 0.0 0 0.0 0 1 0.5
▼ __libc_start_main libc-2.28.so 1 11621 90.1 1129 98.9 10350 89.5 0.11 181 98.4
▶ __cxa_atexit libc-2.28.so 1 2302 19.8 101 8.9 1817 17.6 0.06 13 7.2
▶ __libc_csu_init simple-retpoline 1 121 1.0 43 3.8 340 3.3 0.13 8 4.4
▼ _setjmp libc-2.28.so 1 74 0.6 46 4.1 206 2.0 0.22 4 2.2
▼ __sigsetjmp libc-2.28.so 1 74 100.0 46 100.0 206 100.0 0.22 3 75.0
▶ __sigjmp_save libc-2.28.so 1 0 0.0 0 0.0 0 0.0 0 1 33.3
▼ main simple-retpoline 1 44 0.4 23 2.0 126 1.2 0.18 12 6.6
▼ foo simple-retpoline 2 44 100.0 23 100.0 126 100.0 0.18 10 83.3
bar simple-retpoline 2 22 50.0 6 26.1 61 48.4 0.10 2 20.0
▶ exit libc-2.28.so 1 9029 77.7 878 77.8 7765 75.0 0.11 139 76.8
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190520113728.14389-21-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/scripts/python/exported-sql-viewer.py')
-rwxr-xr-x | tools/perf/scripts/python/exported-sql-viewer.py | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index b3508bd4eb00..f5b1b63995b0 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py | |||
@@ -505,18 +505,24 @@ class CallGraphLevelItemBase(object): | |||
505 | 505 | ||
506 | class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase): | 506 | class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase): |
507 | 507 | ||
508 | def __init__(self, glb, params, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item): | 508 | def __init__(self, glb, params, row, comm_id, thread_id, call_path_id, time, insn_cnt, cyc_cnt, branch_count, parent_item): |
509 | super(CallGraphLevelTwoPlusItemBase, self).__init__(glb, params, row, parent_item) | 509 | super(CallGraphLevelTwoPlusItemBase, self).__init__(glb, params, row, parent_item) |
510 | self.comm_id = comm_id | 510 | self.comm_id = comm_id |
511 | self.thread_id = thread_id | 511 | self.thread_id = thread_id |
512 | self.call_path_id = call_path_id | 512 | self.call_path_id = call_path_id |
513 | self.insn_cnt = insn_cnt | ||
514 | self.cyc_cnt = cyc_cnt | ||
513 | self.branch_count = branch_count | 515 | self.branch_count = branch_count |
514 | self.time = time | 516 | self.time = time |
515 | 517 | ||
516 | def Select(self): | 518 | def Select(self): |
517 | self.query_done = True; | 519 | self.query_done = True; |
518 | query = QSqlQuery(self.glb.db) | 520 | query = QSqlQuery(self.glb.db) |
519 | QueryExec(query, "SELECT call_path_id, name, short_name, COUNT(calls.id), SUM(return_time - call_time), SUM(branch_count)" | 521 | if self.params.have_ipc: |
522 | ipc_str = ", SUM(insn_count), SUM(cyc_count)" | ||
523 | else: | ||
524 | ipc_str = "" | ||
525 | QueryExec(query, "SELECT call_path_id, name, short_name, COUNT(calls.id), SUM(return_time - call_time)" + ipc_str + ", SUM(branch_count)" | ||
520 | " FROM calls" | 526 | " FROM calls" |
521 | " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" | 527 | " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" |
522 | " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" | 528 | " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" |
@@ -527,7 +533,15 @@ class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase): | |||
527 | " GROUP BY call_path_id, name, short_name" | 533 | " GROUP BY call_path_id, name, short_name" |
528 | " ORDER BY call_path_id") | 534 | " ORDER BY call_path_id") |
529 | while query.next(): | 535 | while query.next(): |
530 | child_item = CallGraphLevelThreeItem(self.glb, self.params, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self) | 536 | if self.params.have_ipc: |
537 | insn_cnt = int(query.value(5)) | ||
538 | cyc_cnt = int(query.value(6)) | ||
539 | branch_count = int(query.value(7)) | ||
540 | else: | ||
541 | insn_cnt = 0 | ||
542 | cyc_cnt = 0 | ||
543 | branch_count = int(query.value(5)) | ||
544 | child_item = CallGraphLevelThreeItem(self.glb, self.params, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), insn_cnt, cyc_cnt, branch_count, self) | ||
531 | self.child_items.append(child_item) | 545 | self.child_items.append(child_item) |
532 | self.child_count += 1 | 546 | self.child_count += 1 |
533 | 547 | ||
@@ -535,10 +549,17 @@ class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase): | |||
535 | 549 | ||
536 | class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase): | 550 | class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase): |
537 | 551 | ||
538 | def __init__(self, glb, params, row, comm_id, thread_id, call_path_id, name, dso, count, time, branch_count, parent_item): | 552 | def __init__(self, glb, params, row, comm_id, thread_id, call_path_id, name, dso, count, time, insn_cnt, cyc_cnt, branch_count, parent_item): |
539 | super(CallGraphLevelThreeItem, self).__init__(glb, params, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item) | 553 | super(CallGraphLevelThreeItem, self).__init__(glb, params, row, comm_id, thread_id, call_path_id, time, insn_cnt, cyc_cnt, branch_count, parent_item) |
540 | dso = dsoname(dso) | 554 | dso = dsoname(dso) |
541 | self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ] | 555 | if self.params.have_ipc: |
556 | insn_pcnt = PercentToOneDP(insn_cnt, parent_item.insn_cnt) | ||
557 | cyc_pcnt = PercentToOneDP(cyc_cnt, parent_item.cyc_cnt) | ||
558 | br_pcnt = PercentToOneDP(branch_count, parent_item.branch_count) | ||
559 | ipc = CalcIPC(cyc_cnt, insn_cnt) | ||
560 | self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(insn_cnt), insn_pcnt, str(cyc_cnt), cyc_pcnt, ipc, str(branch_count), br_pcnt ] | ||
561 | else: | ||
562 | self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ] | ||
542 | self.dbid = call_path_id | 563 | self.dbid = call_path_id |
543 | 564 | ||
544 | # Context-sensitive call graph data model level two item | 565 | # Context-sensitive call graph data model level two item |
@@ -546,18 +567,28 @@ class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase): | |||
546 | class CallGraphLevelTwoItem(CallGraphLevelTwoPlusItemBase): | 567 | class CallGraphLevelTwoItem(CallGraphLevelTwoPlusItemBase): |
547 | 568 | ||
548 | def __init__(self, glb, params, row, comm_id, thread_id, pid, tid, parent_item): | 569 | def __init__(self, glb, params, row, comm_id, thread_id, pid, tid, parent_item): |
549 | super(CallGraphLevelTwoItem, self).__init__(glb, params, row, comm_id, thread_id, 1, 0, 0, parent_item) | 570 | super(CallGraphLevelTwoItem, self).__init__(glb, params, row, comm_id, thread_id, 1, 0, 0, 0, 0, parent_item) |
550 | self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""] | 571 | if self.params.have_ipc: |
572 | self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", "", "", "", "", "", ""] | ||
573 | else: | ||
574 | self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""] | ||
551 | self.dbid = thread_id | 575 | self.dbid = thread_id |
552 | 576 | ||
553 | def Select(self): | 577 | def Select(self): |
554 | super(CallGraphLevelTwoItem, self).Select() | 578 | super(CallGraphLevelTwoItem, self).Select() |
555 | for child_item in self.child_items: | 579 | for child_item in self.child_items: |
556 | self.time += child_item.time | 580 | self.time += child_item.time |
581 | self.insn_cnt += child_item.insn_cnt | ||
582 | self.cyc_cnt += child_item.cyc_cnt | ||
557 | self.branch_count += child_item.branch_count | 583 | self.branch_count += child_item.branch_count |
558 | for child_item in self.child_items: | 584 | for child_item in self.child_items: |
559 | child_item.data[4] = PercentToOneDP(child_item.time, self.time) | 585 | child_item.data[4] = PercentToOneDP(child_item.time, self.time) |
560 | child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) | 586 | if self.params.have_ipc: |
587 | child_item.data[6] = PercentToOneDP(child_item.insn_cnt, self.insn_cnt) | ||
588 | child_item.data[8] = PercentToOneDP(child_item.cyc_cnt, self.cyc_cnt) | ||
589 | child_item.data[11] = PercentToOneDP(child_item.branch_count, self.branch_count) | ||
590 | else: | ||
591 | child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) | ||
561 | 592 | ||
562 | # Context-sensitive call graph data model level one item | 593 | # Context-sensitive call graph data model level one item |
563 | 594 | ||
@@ -565,7 +596,10 @@ class CallGraphLevelOneItem(CallGraphLevelItemBase): | |||
565 | 596 | ||
566 | def __init__(self, glb, params, row, comm_id, comm, parent_item): | 597 | def __init__(self, glb, params, row, comm_id, comm, parent_item): |
567 | super(CallGraphLevelOneItem, self).__init__(glb, params, row, parent_item) | 598 | super(CallGraphLevelOneItem, self).__init__(glb, params, row, parent_item) |
568 | self.data = [comm, "", "", "", "", "", ""] | 599 | if self.params.have_ipc: |
600 | self.data = [comm, "", "", "", "", "", "", "", "", "", "", ""] | ||
601 | else: | ||
602 | self.data = [comm, "", "", "", "", "", ""] | ||
569 | self.dbid = comm_id | 603 | self.dbid = comm_id |
570 | 604 | ||
571 | def Select(self): | 605 | def Select(self): |
@@ -694,14 +728,23 @@ class CallGraphModel(CallGraphModelBase): | |||
694 | return CallGraphRootItem(self.glb, self.params) | 728 | return CallGraphRootItem(self.glb, self.params) |
695 | 729 | ||
696 | def columnCount(self, parent=None): | 730 | def columnCount(self, parent=None): |
697 | return 7 | 731 | if self.params.have_ipc: |
732 | return 12 | ||
733 | else: | ||
734 | return 7 | ||
698 | 735 | ||
699 | def columnHeader(self, column): | 736 | def columnHeader(self, column): |
700 | headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] | 737 | if self.params.have_ipc: |
738 | headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Insn Cnt", "Insn Cnt (%)", "Cyc Cnt", "Cyc Cnt (%)", "IPC", "Branch Count ", "Branch Count (%) "] | ||
739 | else: | ||
740 | headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] | ||
701 | return headers[column] | 741 | return headers[column] |
702 | 742 | ||
703 | def columnAlignment(self, column): | 743 | def columnAlignment(self, column): |
704 | alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] | 744 | if self.params.have_ipc: |
745 | alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] | ||
746 | else: | ||
747 | alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] | ||
705 | return alignment[column] | 748 | return alignment[column] |
706 | 749 | ||
707 | def DoFindSelect(self, query, match): | 750 | def DoFindSelect(self, query, match): |