diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2019-05-20 07:37:24 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-06-05 08:47:57 -0400 |
commit | 530e22fd5c6d2c572b1bbdda23eafa01a005fce0 (patch) | |
tree | 398c384fc9e6b9fabbd8dfe04a0d10b09f73bae1 /tools/perf/scripts/python/exported-sql-viewer.py | |
parent | ec7f448e2b2e13d1629300c5881cb3b5e0a99c2f (diff) |
perf scripts python: exported-sql-viewer.py: Add IPC information to the Branch reports
Enhance the "All branches" and "Selected branches" reports to display IPC
information if it is available.
Committer testing:
So, testing this I noticed that it all starts with the left arrow in every
line, that should mean there is some tree there, i.e. look at all those ▶
symbols:
Reports -> All Branches:
Time CPU Command PID TID Branch Type In Tx Insn Cnt Cyc Cnt IPC Branch
▶ 187836112195670 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4f110
+_start (ld-2.28.so)
▶ 187836112195987 7 simple-retpolin 23003 23003 trace end No 0 883 0 7f6f33d4f110 _start (ld-2.28.so) -> 0 unknown
+(unknown)
▶ 187836112199189 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4f110
+_start (ld-2.28.so)
▶ 187836112199189 7 simple-retpolin 23003 23003 call No 0 0 0 7f6f33d4f113 _start+0x3 (ld-2.28.so) -> 7f6f33d4ff50
+_dl_start (ld-2.28.so)
▶ 187836112199544 7 simple-retpolin 23003 23003 trace end No 17 996 0.02 7f6f33d4ff73 _dl_start+0x23 (ld-2.28.so) -> 0
+unknown (unknown)
▶ 187836112200939 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4ff73
+_dl_start+0x23 (ld-2.28.so)
▶ 187836112201229 7 simple-retpolin 23003 23003 trace end No 1 816 0.00 7f6f33d4ff7a _dl_start+0x2a (ld-2.28.so) -> 0
+unknown (unknown)
▶ 187836112203500 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4ff7a
+_dl_start+0x2a (ld-2.28.so)
But if you click on it, that ▶ disappears and a new click doesn't make
it reappear, looks buggy, minor oddity, reported to Adrian.
Reports -> Selected Branches, then ask for branches in the ld-2.28.so
DSO:
Time CPU Command PID TID Branch Type In Tx Insn Cnt Cyc Cnt IPC Branch
▶ 187836112195987 7 simple-retpolin 23003 23003 trace end No 0 883 0 7f6f33d4f110 _start (ld-2.28.so) -> 0 unknown (unknown)
▶ 187836112199189 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4f110 _start (ld-2.28.so)
▶ 187836112199189 7 simple-retpolin 23003 23003 call No 0 0 0 7f6f33d4f113 _start+0x3 (ld-2.28.so) -> 7f6f33d4ff50 _dl_start (ld-2.28.so)
▶ 187836112199544 7 simple-retpolin 23003 23003 trace end No 17 996 0.02 7f6f33d4ff73 _dl_start+0x23 (ld-2.28.so) -> 0 unknown (unknown)
▶ 187836112200939 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4ff73 _dl_start+0x23 (ld-2.28.so)
▶ 187836112201229 7 simple-retpolin 23003 23003 trace end No 1 816 0.00 7f6f33d4ff7a _dl_start+0x2a (ld-2.28.so) -> 0 unknown (unknown)
▶ 187836112203500 7 simple-retpolin 23003 23003 trace begin No 0 0 0 0 unknown (unknown) -> 7f6f33d4ff7a _dl_start+0x2a (ld-2.28.so)
▶ 187836112203528 7 simple-retpolin 23003 23003 unconditional jump No 0 0 0 7f6f33d4ffe7 _dl_start+0x97 (ld-2.28.so) -> 7f6f33d5000b _dl_start+0xbb (ld-2.28.so)
▶ 187836112203528 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d5000f _dl_start+0xbf (ld-2.28.so) -> 7f6f33d4fffb _dl_start+0xab (ld-2.28.so)
▶ 187836112203528 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d5000f _dl_start+0xbf (ld-2.28.so) -> 7f6f33d4fffb _dl_start+0xab (ld-2.28.so)
▶ 187836112203539 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d50025 _dl_start+0xd5 (ld-2.28.so) -> 7f6f33d50210 _dl_start+0x2c0 (ld-2.28.so)
▶ 187836112203539 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d5021a _dl_start+0x2ca (ld-2.28.so) -> 7f6f33d50360 _dl_start+0x410 (ld-2.28.so)
▶ 187836112203539 7 simple-retpolin 23003 23003 unconditional jump No 0 0 0 7f6f33d50377 _dl_start+0x427 (ld-2.28.so) -> 7f6f33d4ffff _dl_start+0xaf (ld-2.28.so)
▶ 187836112203539 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d5000f _dl_start+0xbf (ld-2.28.so) -> 7f6f33d4fffb _dl_start+0xab (ld-2.28.so)
▶ 187836112203562 7 simple-retpolin 23003 23003 conditional jump No 0 0 0 7f6f33d5000f _dl_start+0xbf (ld-2.28.so) -> 7f6f33d4fffb _dl_start+0xab (ld-2.28.so)
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-19-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 | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 6fe553258ce5..a607235c8cd9 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py | |||
@@ -1369,11 +1369,11 @@ class FetchMoreRecordsBar(): | |||
1369 | 1369 | ||
1370 | class BranchLevelTwoItem(): | 1370 | class BranchLevelTwoItem(): |
1371 | 1371 | ||
1372 | def __init__(self, row, text, parent_item): | 1372 | def __init__(self, row, col, text, parent_item): |
1373 | self.row = row | 1373 | self.row = row |
1374 | self.parent_item = parent_item | 1374 | self.parent_item = parent_item |
1375 | self.data = [""] * 8 | 1375 | self.data = [""] * (col + 1) |
1376 | self.data[7] = text | 1376 | self.data[col] = text |
1377 | self.level = 2 | 1377 | self.level = 2 |
1378 | 1378 | ||
1379 | def getParentItem(self): | 1379 | def getParentItem(self): |
@@ -1405,6 +1405,7 @@ class BranchLevelOneItem(): | |||
1405 | self.dbid = data[0] | 1405 | self.dbid = data[0] |
1406 | self.level = 1 | 1406 | self.level = 1 |
1407 | self.query_done = False | 1407 | self.query_done = False |
1408 | self.br_col = len(self.data) - 1 | ||
1408 | 1409 | ||
1409 | def getChildItem(self, row): | 1410 | def getChildItem(self, row): |
1410 | return self.child_items[row] | 1411 | return self.child_items[row] |
@@ -1485,7 +1486,7 @@ class BranchLevelOneItem(): | |||
1485 | while k < 15: | 1486 | while k < 15: |
1486 | byte_str += " " | 1487 | byte_str += " " |
1487 | k += 1 | 1488 | k += 1 |
1488 | self.child_items.append(BranchLevelTwoItem(0, byte_str + " " + text, self)) | 1489 | self.child_items.append(BranchLevelTwoItem(0, self.br_col, byte_str + " " + text, self)) |
1489 | self.child_count += 1 | 1490 | self.child_count += 1 |
1490 | else: | 1491 | else: |
1491 | return | 1492 | return |
@@ -1536,16 +1537,37 @@ class BranchRootItem(): | |||
1536 | def getData(self, column): | 1537 | def getData(self, column): |
1537 | return "" | 1538 | return "" |
1538 | 1539 | ||
1540 | # Calculate instructions per cycle | ||
1541 | |||
1542 | def CalcIPC(cyc_cnt, insn_cnt): | ||
1543 | if cyc_cnt and insn_cnt: | ||
1544 | ipc = Decimal(float(insn_cnt) / cyc_cnt) | ||
1545 | ipc = str(ipc.quantize(Decimal(".01"), rounding=ROUND_HALF_UP)) | ||
1546 | else: | ||
1547 | ipc = "0" | ||
1548 | return ipc | ||
1549 | |||
1539 | # Branch data preparation | 1550 | # Branch data preparation |
1540 | 1551 | ||
1541 | def BranchDataPrep(query): | 1552 | def BranchDataPrepBr(query, data): |
1542 | data = [] | ||
1543 | for i in xrange(0, 8): | ||
1544 | data.append(query.value(i)) | ||
1545 | data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) + | 1553 | data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) + |
1546 | " (" + dsoname(query.value(11)) + ")" + " -> " + | 1554 | " (" + dsoname(query.value(11)) + ")" + " -> " + |
1547 | tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) + | 1555 | tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) + |
1548 | " (" + dsoname(query.value(15)) + ")") | 1556 | " (" + dsoname(query.value(15)) + ")") |
1557 | |||
1558 | def BranchDataPrepIPC(query, data): | ||
1559 | insn_cnt = query.value(16) | ||
1560 | cyc_cnt = query.value(17) | ||
1561 | ipc = CalcIPC(cyc_cnt, insn_cnt) | ||
1562 | data.append(insn_cnt) | ||
1563 | data.append(cyc_cnt) | ||
1564 | data.append(ipc) | ||
1565 | |||
1566 | def BranchDataPrep(query): | ||
1567 | data = [] | ||
1568 | for i in xrange(0, 8): | ||
1569 | data.append(query.value(i)) | ||
1570 | BranchDataPrepBr(query, data) | ||
1549 | return data | 1571 | return data |
1550 | 1572 | ||
1551 | def BranchDataPrepWA(query): | 1573 | def BranchDataPrepWA(query): |
@@ -1555,10 +1577,26 @@ def BranchDataPrepWA(query): | |||
1555 | data.append("{:>19}".format(query.value(1))) | 1577 | data.append("{:>19}".format(query.value(1))) |
1556 | for i in xrange(2, 8): | 1578 | for i in xrange(2, 8): |
1557 | data.append(query.value(i)) | 1579 | data.append(query.value(i)) |
1558 | data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) + | 1580 | BranchDataPrepBr(query, data) |
1559 | " (" + dsoname(query.value(11)) + ")" + " -> " + | 1581 | return data |
1560 | tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) + | 1582 | |
1561 | " (" + dsoname(query.value(15)) + ")") | 1583 | def BranchDataWithIPCPrep(query): |
1584 | data = [] | ||
1585 | for i in xrange(0, 8): | ||
1586 | data.append(query.value(i)) | ||
1587 | BranchDataPrepIPC(query, data) | ||
1588 | BranchDataPrepBr(query, data) | ||
1589 | return data | ||
1590 | |||
1591 | def BranchDataWithIPCPrepWA(query): | ||
1592 | data = [] | ||
1593 | data.append(query.value(0)) | ||
1594 | # Workaround pyside failing to handle large integers (i.e. time) in python3 by converting to a string | ||
1595 | data.append("{:>19}".format(query.value(1))) | ||
1596 | for i in xrange(2, 8): | ||
1597 | data.append(query.value(i)) | ||
1598 | BranchDataPrepIPC(query, data) | ||
1599 | BranchDataPrepBr(query, data) | ||
1562 | return data | 1600 | return data |
1563 | 1601 | ||
1564 | # Branch data model | 1602 | # Branch data model |
@@ -1572,10 +1610,20 @@ class BranchModel(TreeModel): | |||
1572 | self.event_id = event_id | 1610 | self.event_id = event_id |
1573 | self.more = True | 1611 | self.more = True |
1574 | self.populated = 0 | 1612 | self.populated = 0 |
1613 | self.have_ipc = IsSelectable(glb.db, "samples", columns = "insn_count, cyc_count") | ||
1614 | if self.have_ipc: | ||
1615 | select_ipc = ", insn_count, cyc_count" | ||
1616 | prep_fn = BranchDataWithIPCPrep | ||
1617 | prep_wa_fn = BranchDataWithIPCPrepWA | ||
1618 | else: | ||
1619 | select_ipc = "" | ||
1620 | prep_fn = BranchDataPrep | ||
1621 | prep_wa_fn = BranchDataPrepWA | ||
1575 | sql = ("SELECT samples.id, time, cpu, comm, pid, tid, branch_types.name," | 1622 | sql = ("SELECT samples.id, time, cpu, comm, pid, tid, branch_types.name," |
1576 | " CASE WHEN in_tx = '0' THEN 'No' ELSE 'Yes' END," | 1623 | " CASE WHEN in_tx = '0' THEN 'No' ELSE 'Yes' END," |
1577 | " ip, symbols.name, sym_offset, dsos.short_name," | 1624 | " ip, symbols.name, sym_offset, dsos.short_name," |
1578 | " to_ip, to_symbols.name, to_sym_offset, to_dsos.short_name" | 1625 | " to_ip, to_symbols.name, to_sym_offset, to_dsos.short_name" |
1626 | + select_ipc + | ||
1579 | " FROM samples" | 1627 | " FROM samples" |
1580 | " INNER JOIN comms ON comm_id = comms.id" | 1628 | " INNER JOIN comms ON comm_id = comms.id" |
1581 | " INNER JOIN threads ON thread_id = threads.id" | 1629 | " INNER JOIN threads ON thread_id = threads.id" |
@@ -1589,9 +1637,9 @@ class BranchModel(TreeModel): | |||
1589 | " ORDER BY samples.id" | 1637 | " ORDER BY samples.id" |
1590 | " LIMIT " + str(glb_chunk_sz)) | 1638 | " LIMIT " + str(glb_chunk_sz)) |
1591 | if pyside_version_1 and sys.version_info[0] == 3: | 1639 | if pyside_version_1 and sys.version_info[0] == 3: |
1592 | prep = BranchDataPrepWA | 1640 | prep = prep_fn |
1593 | else: | 1641 | else: |
1594 | prep = BranchDataPrep | 1642 | prep = prep_wa_fn |
1595 | self.fetcher = SQLFetcher(glb, sql, prep, self.AddSample) | 1643 | self.fetcher = SQLFetcher(glb, sql, prep, self.AddSample) |
1596 | self.fetcher.done.connect(self.Update) | 1644 | self.fetcher.done.connect(self.Update) |
1597 | self.fetcher.Fetch(glb_chunk_sz) | 1645 | self.fetcher.Fetch(glb_chunk_sz) |
@@ -1600,13 +1648,23 @@ class BranchModel(TreeModel): | |||
1600 | return BranchRootItem() | 1648 | return BranchRootItem() |
1601 | 1649 | ||
1602 | def columnCount(self, parent=None): | 1650 | def columnCount(self, parent=None): |
1603 | return 8 | 1651 | if self.have_ipc: |
1652 | return 11 | ||
1653 | else: | ||
1654 | return 8 | ||
1604 | 1655 | ||
1605 | def columnHeader(self, column): | 1656 | def columnHeader(self, column): |
1606 | return ("Time", "CPU", "Command", "PID", "TID", "Branch Type", "In Tx", "Branch")[column] | 1657 | if self.have_ipc: |
1658 | return ("Time", "CPU", "Command", "PID", "TID", "Branch Type", "In Tx", "Insn Cnt", "Cyc Cnt", "IPC", "Branch")[column] | ||
1659 | else: | ||
1660 | return ("Time", "CPU", "Command", "PID", "TID", "Branch Type", "In Tx", "Branch")[column] | ||
1607 | 1661 | ||
1608 | def columnFont(self, column): | 1662 | def columnFont(self, column): |
1609 | if column != 7: | 1663 | if self.have_ipc: |
1664 | br_col = 10 | ||
1665 | else: | ||
1666 | br_col = 7 | ||
1667 | if column != br_col: | ||
1610 | return None | 1668 | return None |
1611 | return QFont("Monospace") | 1669 | return QFont("Monospace") |
1612 | 1670 | ||
@@ -2114,10 +2172,10 @@ def GetEventList(db): | |||
2114 | 2172 | ||
2115 | # Is a table selectable | 2173 | # Is a table selectable |
2116 | 2174 | ||
2117 | def IsSelectable(db, table, sql = ""): | 2175 | def IsSelectable(db, table, sql = "", columns = "*"): |
2118 | query = QSqlQuery(db) | 2176 | query = QSqlQuery(db) |
2119 | try: | 2177 | try: |
2120 | QueryExec(query, "SELECT * FROM " + table + " " + sql + " LIMIT 1") | 2178 | QueryExec(query, "SELECT " + columns + " FROM " + table + " " + sql + " LIMIT 1") |
2121 | except: | 2179 | except: |
2122 | return False | 2180 | return False |
2123 | return True | 2181 | return True |
@@ -2854,6 +2912,12 @@ cd xed | |||
2854 | sudo ./mfile.py --prefix=/usr/local install | 2912 | sudo ./mfile.py --prefix=/usr/local install |
2855 | sudo ldconfig | 2913 | sudo ldconfig |
2856 | </pre> | 2914 | </pre> |
2915 | <h3>Instructions per Cycle (IPC)</h3> | ||
2916 | If available, IPC information is displayed in columns 'insn_cnt', 'cyc_cnt' and 'IPC'. | ||
2917 | <p><b>Intel PT note:</b> The information applies to the blocks of code ending with, and including, that branch. | ||
2918 | Due to the granularity of timing information, the number of cycles for some code blocks will not be known. | ||
2919 | In that case, 'insn_cnt', 'cyc_cnt' and 'IPC' are zero, but when 'IPC' is displayed it covers the period | ||
2920 | since the previous displayed 'IPC'. | ||
2857 | <h3>Find</h3> | 2921 | <h3>Find</h3> |
2858 | Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. | 2922 | Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. |
2859 | Refer to Python documentation for the regular expression syntax. | 2923 | Refer to Python documentation for the regular expression syntax. |