aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts/python/exported-sql-viewer.py
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2019-05-20 07:37:24 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-06-05 08:47:57 -0400
commit530e22fd5c6d2c572b1bbdda23eafa01a005fce0 (patch)
tree398c384fc9e6b9fabbd8dfe04a0d10b09f73bae1 /tools/perf/scripts/python/exported-sql-viewer.py
parentec7f448e2b2e13d1629300c5881cb3b5e0a99c2f (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-xtools/perf/scripts/python/exported-sql-viewer.py102
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
1370class BranchLevelTwoItem(): 1370class 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
1542def 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
1541def BranchDataPrep(query): 1552def 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
1558def 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
1566def 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
1551def BranchDataPrepWA(query): 1573def 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)) + ")") 1583def 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
1591def 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
2117def IsSelectable(db, table, sql = ""): 2175def 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
2854sudo ./mfile.py --prefix=/usr/local install 2912sudo ./mfile.py --prefix=/usr/local install
2855sudo ldconfig 2913sudo ldconfig
2856</pre> 2914</pre>
2915<h3>Instructions per Cycle (IPC)</h3>
2916If 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.
2918Due to the granularity of timing information, the number of cycles for some code blocks will not be known.
2919In that case, 'insn_cnt', 'cyc_cnt' and 'IPC' are zero, but when 'IPC' is displayed it covers the period
2920since the previous displayed 'IPC'.
2857<h3>Find</h3> 2921<h3>Find</h3>
2858Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. 2922Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.
2859Refer to Python documentation for the regular expression syntax. 2923Refer to Python documentation for the regular expression syntax.