aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts/python
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/scripts/python')
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Build2
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py76
-rw-r--r--tools/perf/scripts/python/compaction-times.py8
-rw-r--r--tools/perf/scripts/python/event_analyzing_sample.py48
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py16
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py14
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py857
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py43
-rw-r--r--tools/perf/scripts/python/futex-contention.py10
-rw-r--r--tools/perf/scripts/python/intel-pt-events.py60
-rw-r--r--tools/perf/scripts/python/mem-phys-addr.py25
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py12
-rw-r--r--tools/perf/scripts/python/netdev-times.py92
-rw-r--r--tools/perf/scripts/python/powerpc-hcalls.py18
-rw-r--r--tools/perf/scripts/python/sched-migration.py8
-rw-r--r--tools/perf/scripts/python/sctop.py27
-rwxr-xr-xtools/perf/scripts/python/stackcollapse.py9
-rw-r--r--tools/perf/scripts/python/stat-cpi.py11
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py51
-rw-r--r--tools/perf/scripts/python/syscall-counts.py35
20 files changed, 931 insertions, 491 deletions
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
index aefc15c9444a..7d0e33ce6aba 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Build
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Build
@@ -1,3 +1,3 @@
1libperf-y += Context.o 1perf-y += Context.o
2 2
3CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs 3CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 334599c6032c..d2c22954800d 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -7,6 +7,8 @@
7# events, etc. Basically, if this script runs successfully and 7# events, etc. Basically, if this script runs successfully and
8# displays expected results, Python scripting support should be ok. 8# displays expected results, Python scripting support should be ok.
9 9
10from __future__ import print_function
11
10import os 12import os
11import sys 13import sys
12 14
@@ -19,64 +21,64 @@ from perf_trace_context import *
19unhandled = autodict() 21unhandled = autodict()
20 22
21def trace_begin(): 23def trace_begin():
22 print "trace_begin" 24 print("trace_begin")
23 pass 25 pass
24 26
25def trace_end(): 27def trace_end():
26 print_unhandled() 28 print_unhandled()
27 29
28def irq__softirq_entry(event_name, context, common_cpu, 30def irq__softirq_entry(event_name, context, common_cpu,
29 common_secs, common_nsecs, common_pid, common_comm, 31 common_secs, common_nsecs, common_pid, common_comm,
30 common_callchain, vec): 32 common_callchain, vec):
31 print_header(event_name, common_cpu, common_secs, common_nsecs, 33 print_header(event_name, common_cpu, common_secs, common_nsecs,
32 common_pid, common_comm) 34 common_pid, common_comm)
33 35
34 print_uncommon(context) 36 print_uncommon(context)
35 37
36 print "vec=%s\n" % \ 38 print("vec=%s" % (symbol_str("irq__softirq_entry", "vec", vec)))
37 (symbol_str("irq__softirq_entry", "vec", vec)),
38 39
39def kmem__kmalloc(event_name, context, common_cpu, 40def kmem__kmalloc(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm, 41 common_secs, common_nsecs, common_pid, common_comm,
41 common_callchain, call_site, ptr, bytes_req, bytes_alloc, 42 common_callchain, call_site, ptr, bytes_req, bytes_alloc,
42 gfp_flags): 43 gfp_flags):
43 print_header(event_name, common_cpu, common_secs, common_nsecs, 44 print_header(event_name, common_cpu, common_secs, common_nsecs,
44 common_pid, common_comm) 45 common_pid, common_comm)
45 46
46 print_uncommon(context) 47 print_uncommon(context)
47 48
48 print "call_site=%u, ptr=%u, bytes_req=%u, " \ 49 print("call_site=%u, ptr=%u, bytes_req=%u, "
49 "bytes_alloc=%u, gfp_flags=%s\n" % \ 50 "bytes_alloc=%u, gfp_flags=%s" %
50 (call_site, ptr, bytes_req, bytes_alloc, 51 (call_site, ptr, bytes_req, bytes_alloc,
51 52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)))
52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
53 53
54def trace_unhandled(event_name, context, event_fields_dict): 54def trace_unhandled(event_name, context, event_fields_dict):
55 try: 55 try:
56 unhandled[event_name] += 1 56 unhandled[event_name] += 1
57 except TypeError: 57 except TypeError:
58 unhandled[event_name] = 1 58 unhandled[event_name] = 1
59 59
60def print_header(event_name, cpu, secs, nsecs, pid, comm): 60def print_header(event_name, cpu, secs, nsecs, pid, comm):
61 print "%-20s %5u %05u.%09u %8u %-20s " % \ 61 print("%-20s %5u %05u.%09u %8u %-20s " %
62 (event_name, cpu, secs, nsecs, pid, comm), 62 (event_name, cpu, secs, nsecs, pid, comm),
63 end=' ')
63 64
64# print trace fields not included in handler args 65# print trace fields not included in handler args
65def print_uncommon(context): 66def print_uncommon(context):
66 print "common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, " \ 67 print("common_preempt_count=%d, common_flags=%s, "
67 % (common_pc(context), trace_flag_str(common_flags(context)), \ 68 "common_lock_depth=%d, " %
68 common_lock_depth(context)) 69 (common_pc(context), trace_flag_str(common_flags(context)),
70 common_lock_depth(context)))
69 71
70def print_unhandled(): 72def print_unhandled():
71 keys = unhandled.keys() 73 keys = unhandled.keys()
72 if not keys: 74 if not keys:
73 return 75 return
74 76
75 print "\nunhandled events:\n\n", 77 print("\nunhandled events:\n")
76 78
77 print "%-40s %10s\n" % ("event", "count"), 79 print("%-40s %10s" % ("event", "count"))
78 print "%-40s %10s\n" % ("----------------------------------------", \ 80 print("%-40s %10s" % ("----------------------------------------",
79 "-----------"), 81 "-----------"))
80 82
81 for event_name in keys: 83 for event_name in keys:
82 print "%-40s %10d\n" % (event_name, unhandled[event_name]) 84 print("%-40s %10d\n" % (event_name, unhandled[event_name]))
diff --git a/tools/perf/scripts/python/compaction-times.py b/tools/perf/scripts/python/compaction-times.py
index 239cb0568ec3..2560a042dc6f 100644
--- a/tools/perf/scripts/python/compaction-times.py
+++ b/tools/perf/scripts/python/compaction-times.py
@@ -216,15 +216,15 @@ def compaction__mm_compaction_migratepages(event_name, context, common_cpu,
216 pair(nr_migrated, nr_failed), None, None) 216 pair(nr_migrated, nr_failed), None, None)
217 217
218def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu, 218def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu,
219 common_secs, common_nsecs, common_pid, common_comm, 219 common_secs, common_nsecs, common_pid, common_comm,
220 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 220 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
221 221
222 chead.increment_pending(common_pid, 222 chead.increment_pending(common_pid,
223 None, pair(nr_scanned, nr_taken), None) 223 None, pair(nr_scanned, nr_taken), None)
224 224
225def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu, 225def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu,
226 common_secs, common_nsecs, common_pid, common_comm, 226 common_secs, common_nsecs, common_pid, common_comm,
227 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 227 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
228 228
229 chead.increment_pending(common_pid, 229 chead.increment_pending(common_pid,
230 None, None, pair(nr_scanned, nr_taken)) 230 None, None, pair(nr_scanned, nr_taken))
diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py
index 4e843b9864ec..aa1e2cfa26a6 100644
--- a/tools/perf/scripts/python/event_analyzing_sample.py
+++ b/tools/perf/scripts/python/event_analyzing_sample.py
@@ -15,6 +15,8 @@
15# for a x86 HW PMU event: PEBS with load latency data. 15# for a x86 HW PMU event: PEBS with load latency data.
16# 16#
17 17
18from __future__ import print_function
19
18import os 20import os
19import sys 21import sys
20import math 22import math
@@ -37,7 +39,7 @@ con = sqlite3.connect("/dev/shm/perf.db")
37con.isolation_level = None 39con.isolation_level = None
38 40
39def trace_begin(): 41def trace_begin():
40 print "In trace_begin:\n" 42 print("In trace_begin:\n")
41 43
42 # 44 #
43 # Will create several tables at the start, pebs_ll is for PEBS data with 45 # Will create several tables at the start, pebs_ll is for PEBS data with
@@ -76,12 +78,12 @@ def process_event(param_dict):
76 name = param_dict["ev_name"] 78 name = param_dict["ev_name"]
77 79
78 # Symbol and dso info are not always resolved 80 # Symbol and dso info are not always resolved
79 if (param_dict.has_key("dso")): 81 if ("dso" in param_dict):
80 dso = param_dict["dso"] 82 dso = param_dict["dso"]
81 else: 83 else:
82 dso = "Unknown_dso" 84 dso = "Unknown_dso"
83 85
84 if (param_dict.has_key("symbol")): 86 if ("symbol" in param_dict):
85 symbol = param_dict["symbol"] 87 symbol = param_dict["symbol"]
86 else: 88 else:
87 symbol = "Unknown_symbol" 89 symbol = "Unknown_symbol"
@@ -102,7 +104,7 @@ def insert_db(event):
102 event.ip, event.status, event.dse, event.dla, event.lat)) 104 event.ip, event.status, event.dse, event.dla, event.lat))
103 105
104def trace_end(): 106def trace_end():
105 print "In trace_end:\n" 107 print("In trace_end:\n")
106 # We show the basic info for the 2 type of event classes 108 # We show the basic info for the 2 type of event classes
107 show_general_events() 109 show_general_events()
108 show_pebs_ll() 110 show_pebs_ll()
@@ -123,29 +125,29 @@ def show_general_events():
123 # Check the total record number in the table 125 # Check the total record number in the table
124 count = con.execute("select count(*) from gen_events") 126 count = con.execute("select count(*) from gen_events")
125 for t in count: 127 for t in count:
126 print "There is %d records in gen_events table" % t[0] 128 print("There is %d records in gen_events table" % t[0])
127 if t[0] == 0: 129 if t[0] == 0:
128 return 130 return
129 131
130 print "Statistics about the general events grouped by thread/symbol/dso: \n" 132 print("Statistics about the general events grouped by thread/symbol/dso: \n")
131 133
132 # Group by thread 134 # Group by thread
133 commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") 135 commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)")
134 print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 136 print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
135 for row in commq: 137 for row in commq:
136 print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 138 print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
137 139
138 # Group by symbol 140 # Group by symbol
139 print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 141 print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
140 symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") 142 symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)")
141 for row in symbolq: 143 for row in symbolq:
142 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 144 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
143 145
144 # Group by dso 146 # Group by dso
145 print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) 147 print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74))
146 dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") 148 dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)")
147 for row in dsoq: 149 for row in dsoq:
148 print "%40s %8d %s" % (row[0], row[1], num2sym(row[1])) 150 print("%40s %8d %s" % (row[0], row[1], num2sym(row[1])))
149 151
150# 152#
151# This function just shows the basic info, and we could do more with the 153# This function just shows the basic info, and we could do more with the
@@ -156,35 +158,35 @@ def show_pebs_ll():
156 158
157 count = con.execute("select count(*) from pebs_ll") 159 count = con.execute("select count(*) from pebs_ll")
158 for t in count: 160 for t in count:
159 print "There is %d records in pebs_ll table" % t[0] 161 print("There is %d records in pebs_ll table" % t[0])
160 if t[0] == 0: 162 if t[0] == 0:
161 return 163 return
162 164
163 print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" 165 print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n")
164 166
165 # Group by thread 167 # Group by thread
166 commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") 168 commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)")
167 print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 169 print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
168 for row in commq: 170 for row in commq:
169 print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 171 print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
170 172
171 # Group by symbol 173 # Group by symbol
172 print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 174 print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
173 symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") 175 symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)")
174 for row in symbolq: 176 for row in symbolq:
175 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 177 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
176 178
177 # Group by dse 179 # Group by dse
178 dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") 180 dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)")
179 print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) 181 print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58))
180 for row in dseq: 182 for row in dseq:
181 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 183 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
182 184
183 # Group by latency 185 # Group by latency
184 latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") 186 latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat")
185 print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) 187 print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58))
186 for row in latq: 188 for row in latq:
187 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 189 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
188 190
189def trace_unhandled(event_name, context, event_fields_dict): 191def trace_unhandled(event_name, context, event_fields_dict):
190 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 192 print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 0564dd7377f2..390a351d15ea 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -394,7 +394,8 @@ if perf_db_export_calls:
394 'call_id bigint,' 394 'call_id bigint,'
395 'return_id bigint,' 395 'return_id bigint,'
396 'parent_call_path_id bigint,' 396 'parent_call_path_id bigint,'
397 'flags integer)') 397 'flags integer,'
398 'parent_id bigint)')
398 399
399do_query(query, 'CREATE VIEW machines_view AS ' 400do_query(query, 'CREATE VIEW machines_view AS '
400 'SELECT ' 401 'SELECT '
@@ -478,8 +479,9 @@ if perf_db_export_calls:
478 'branch_count,' 479 'branch_count,'
479 'call_id,' 480 'call_id,'
480 'return_id,' 481 'return_id,'
481 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' 482 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,'
482 'parent_call_path_id' 483 'parent_call_path_id,'
484 'calls.parent_id'
483 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 485 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
484 486
485do_query(query, 'CREATE VIEW samples_view AS ' 487do_query(query, 'CREATE VIEW samples_view AS '
@@ -575,6 +577,7 @@ def trace_begin():
575 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 577 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
576 if perf_db_export_calls or perf_db_export_callchains: 578 if perf_db_export_calls or perf_db_export_callchains:
577 call_path_table(0, 0, 0, 0) 579 call_path_table(0, 0, 0, 0)
580 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
578 581
579unhandled_count = 0 582unhandled_count = 0
580 583
@@ -657,6 +660,7 @@ def trace_end():
657 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' 660 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
658 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') 661 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
659 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 662 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
663 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
660 664
661 if (unhandled_count): 665 if (unhandled_count):
662 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 666 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
@@ -728,7 +732,7 @@ def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
728 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) 732 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
729 call_path_file.write(value) 733 call_path_file.write(value)
730 734
731def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): 735def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, *x):
732 fmt = "!hiqiqiqiqiqiqiqiqiqiqii" 736 fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiq"
733 value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) 737 value = struct.pack(fmt, 12, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id)
734 call_file.write(value) 738 call_file.write(value)
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index 245caf2643ed..eb63e6c7107f 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -222,7 +222,8 @@ if perf_db_export_calls:
222 'call_id bigint,' 222 'call_id bigint,'
223 'return_id bigint,' 223 'return_id bigint,'
224 'parent_call_path_id bigint,' 224 'parent_call_path_id bigint,'
225 'flags integer)') 225 'flags integer,'
226 'parent_id bigint)')
226 227
227# printf was added to sqlite in version 3.8.3 228# printf was added to sqlite in version 3.8.3
228sqlite_has_printf = False 229sqlite_has_printf = False
@@ -320,8 +321,9 @@ if perf_db_export_calls:
320 'branch_count,' 321 'branch_count,'
321 'call_id,' 322 'call_id,'
322 'return_id,' 323 'return_id,'
323 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' 324 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,'
324 'parent_call_path_id' 325 'parent_call_path_id,'
326 'parent_id'
325 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 327 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
326 328
327do_query(query, 'CREATE VIEW samples_view AS ' 329do_query(query, 'CREATE VIEW samples_view AS '
@@ -373,7 +375,7 @@ if perf_db_export_calls or perf_db_export_callchains:
373 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)") 375 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
374if perf_db_export_calls: 376if perf_db_export_calls:
375 call_query = QSqlQuery(db) 377 call_query = QSqlQuery(db)
376 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 378 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
377 379
378def trace_begin(): 380def trace_begin():
379 print datetime.datetime.today(), "Writing records..." 381 print datetime.datetime.today(), "Writing records..."
@@ -388,6 +390,7 @@ def trace_begin():
388 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 390 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
389 if perf_db_export_calls or perf_db_export_callchains: 391 if perf_db_export_calls or perf_db_export_callchains:
390 call_path_table(0, 0, 0, 0) 392 call_path_table(0, 0, 0, 0)
393 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
391 394
392unhandled_count = 0 395unhandled_count = 0
393 396
@@ -397,6 +400,7 @@ def trace_end():
397 print datetime.datetime.today(), "Adding indexes" 400 print datetime.datetime.today(), "Adding indexes"
398 if perf_db_export_calls: 401 if perf_db_export_calls:
399 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 402 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
403 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
400 404
401 if (unhandled_count): 405 if (unhandled_count):
402 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 406 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
@@ -452,4 +456,4 @@ def call_path_table(*x):
452 bind_exec(call_path_query, 4, x) 456 bind_exec(call_path_query, 4, x)
453 457
454def call_return_table(*x): 458def call_return_table(*x):
455 bind_exec(call_query, 11, x) 459 bind_exec(call_query, 12, x)
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
index f278ce5ebab7..afec9479ca7f 100755
--- a/tools/perf/scripts/python/exported-sql-viewer.py
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python2 1#!/usr/bin/env python2
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3# exported-sql-viewer.py: view data from sql database 3# exported-sql-viewer.py: view data from sql database
4# Copyright (c) 2014-2018, Intel Corporation. 4# Copyright (c) 2014-2018, Intel Corporation.
@@ -167,9 +167,10 @@ class Thread(QThread):
167 167
168class TreeModel(QAbstractItemModel): 168class TreeModel(QAbstractItemModel):
169 169
170 def __init__(self, root, parent=None): 170 def __init__(self, glb, parent=None):
171 super(TreeModel, self).__init__(parent) 171 super(TreeModel, self).__init__(parent)
172 self.root = root 172 self.glb = glb
173 self.root = self.GetRoot()
173 self.last_row_read = 0 174 self.last_row_read = 0
174 175
175 def Item(self, parent): 176 def Item(self, parent):
@@ -557,24 +558,12 @@ class CallGraphRootItem(CallGraphLevelItemBase):
557 self.child_items.append(child_item) 558 self.child_items.append(child_item)
558 self.child_count += 1 559 self.child_count += 1
559 560
560# Context-sensitive call graph data model 561# Context-sensitive call graph data model base
561 562
562class CallGraphModel(TreeModel): 563class CallGraphModelBase(TreeModel):
563 564
564 def __init__(self, glb, parent=None): 565 def __init__(self, glb, parent=None):
565 super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent) 566 super(CallGraphModelBase, self).__init__(glb, parent)
566 self.glb = glb
567
568 def columnCount(self, parent=None):
569 return 7
570
571 def columnHeader(self, column):
572 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
573 return headers[column]
574
575 def columnAlignment(self, column):
576 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
577 return alignment[column]
578 567
579 def FindSelect(self, value, pattern, query): 568 def FindSelect(self, value, pattern, query):
580 if pattern: 569 if pattern:
@@ -594,34 +583,7 @@ class CallGraphModel(TreeModel):
594 match = " GLOB '" + str(value) + "'" 583 match = " GLOB '" + str(value) + "'"
595 else: 584 else:
596 match = " = '" + str(value) + "'" 585 match = " = '" + str(value) + "'"
597 QueryExec(query, "SELECT call_path_id, comm_id, thread_id" 586 self.DoFindSelect(query, match)
598 " FROM calls"
599 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
600 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
601 " WHERE symbols.name" + match +
602 " GROUP BY comm_id, thread_id, call_path_id"
603 " ORDER BY comm_id, thread_id, call_path_id")
604
605 def FindPath(self, query):
606 # Turn the query result into a list of ids that the tree view can walk
607 # to open the tree at the right place.
608 ids = []
609 parent_id = query.value(0)
610 while parent_id:
611 ids.insert(0, parent_id)
612 q2 = QSqlQuery(self.glb.db)
613 QueryExec(q2, "SELECT parent_id"
614 " FROM call_paths"
615 " WHERE id = " + str(parent_id))
616 if not q2.next():
617 break
618 parent_id = q2.value(0)
619 # The call path root is not used
620 if ids[0] == 1:
621 del ids[0]
622 ids.insert(0, query.value(2))
623 ids.insert(0, query.value(1))
624 return ids
625 587
626 def Found(self, query, found): 588 def Found(self, query, found):
627 if found: 589 if found:
@@ -675,6 +637,201 @@ class CallGraphModel(TreeModel):
675 def FindDone(self, thread, callback, ids): 637 def FindDone(self, thread, callback, ids):
676 callback(ids) 638 callback(ids)
677 639
640# Context-sensitive call graph data model
641
642class CallGraphModel(CallGraphModelBase):
643
644 def __init__(self, glb, parent=None):
645 super(CallGraphModel, self).__init__(glb, parent)
646
647 def GetRoot(self):
648 return CallGraphRootItem(self.glb)
649
650 def columnCount(self, parent=None):
651 return 7
652
653 def columnHeader(self, column):
654 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
655 return headers[column]
656
657 def columnAlignment(self, column):
658 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
659 return alignment[column]
660
661 def DoFindSelect(self, query, match):
662 QueryExec(query, "SELECT call_path_id, comm_id, thread_id"
663 " FROM calls"
664 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
665 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
666 " WHERE symbols.name" + match +
667 " GROUP BY comm_id, thread_id, call_path_id"
668 " ORDER BY comm_id, thread_id, call_path_id")
669
670 def FindPath(self, query):
671 # Turn the query result into a list of ids that the tree view can walk
672 # to open the tree at the right place.
673 ids = []
674 parent_id = query.value(0)
675 while parent_id:
676 ids.insert(0, parent_id)
677 q2 = QSqlQuery(self.glb.db)
678 QueryExec(q2, "SELECT parent_id"
679 " FROM call_paths"
680 " WHERE id = " + str(parent_id))
681 if not q2.next():
682 break
683 parent_id = q2.value(0)
684 # The call path root is not used
685 if ids[0] == 1:
686 del ids[0]
687 ids.insert(0, query.value(2))
688 ids.insert(0, query.value(1))
689 return ids
690
691# Call tree data model level 2+ item base
692
693class CallTreeLevelTwoPlusItemBase(CallGraphLevelItemBase):
694
695 def __init__(self, glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item):
696 super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, row, parent_item)
697 self.comm_id = comm_id
698 self.thread_id = thread_id
699 self.calls_id = calls_id
700 self.branch_count = branch_count
701 self.time = time
702
703 def Select(self):
704 self.query_done = True;
705 if self.calls_id == 0:
706 comm_thread = " AND comm_id = " + str(self.comm_id) + " AND thread_id = " + str(self.thread_id)
707 else:
708 comm_thread = ""
709 query = QSqlQuery(self.glb.db)
710 QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time, branch_count"
711 " FROM calls"
712 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
713 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
714 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
715 " WHERE calls.parent_id = " + str(self.calls_id) + comm_thread +
716 " ORDER BY call_time, calls.id")
717 while query.next():
718 child_item = CallTreeLevelThreeItem(self.glb, 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)
719 self.child_items.append(child_item)
720 self.child_count += 1
721
722# Call tree data model level three item
723
724class CallTreeLevelThreeItem(CallTreeLevelTwoPlusItemBase):
725
726 def __init__(self, glb, row, comm_id, thread_id, calls_id, name, dso, count, time, branch_count, parent_item):
727 super(CallTreeLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item)
728 dso = dsoname(dso)
729 self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]
730 self.dbid = calls_id
731
732# Call tree data model level two item
733
734class CallTreeLevelTwoItem(CallTreeLevelTwoPlusItemBase):
735
736 def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):
737 super(CallTreeLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 0, 0, 0, parent_item)
738 self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]
739 self.dbid = thread_id
740
741 def Select(self):
742 super(CallTreeLevelTwoItem, self).Select()
743 for child_item in self.child_items:
744 self.time += child_item.time
745 self.branch_count += child_item.branch_count
746 for child_item in self.child_items:
747 child_item.data[4] = PercentToOneDP(child_item.time, self.time)
748 child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count)
749
750# Call tree data model level one item
751
752class CallTreeLevelOneItem(CallGraphLevelItemBase):
753
754 def __init__(self, glb, row, comm_id, comm, parent_item):
755 super(CallTreeLevelOneItem, self).__init__(glb, row, parent_item)
756 self.data = [comm, "", "", "", "", "", ""]
757 self.dbid = comm_id
758
759 def Select(self):
760 self.query_done = True;
761 query = QSqlQuery(self.glb.db)
762 QueryExec(query, "SELECT thread_id, pid, tid"
763 " FROM comm_threads"
764 " INNER JOIN threads ON thread_id = threads.id"
765 " WHERE comm_id = " + str(self.dbid))
766 while query.next():
767 child_item = CallTreeLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)
768 self.child_items.append(child_item)
769 self.child_count += 1
770
771# Call tree data model root item
772
773class CallTreeRootItem(CallGraphLevelItemBase):
774
775 def __init__(self, glb):
776 super(CallTreeRootItem, self).__init__(glb, 0, None)
777 self.dbid = 0
778 self.query_done = True;
779 query = QSqlQuery(glb.db)
780 QueryExec(query, "SELECT id, comm FROM comms")
781 while query.next():
782 if not query.value(0):
783 continue
784 child_item = CallTreeLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)
785 self.child_items.append(child_item)
786 self.child_count += 1
787
788# Call Tree data model
789
790class CallTreeModel(CallGraphModelBase):
791
792 def __init__(self, glb, parent=None):
793 super(CallTreeModel, self).__init__(glb, parent)
794
795 def GetRoot(self):
796 return CallTreeRootItem(self.glb)
797
798 def columnCount(self, parent=None):
799 return 7
800
801 def columnHeader(self, column):
802 headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
803 return headers[column]
804
805 def columnAlignment(self, column):
806 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
807 return alignment[column]
808
809 def DoFindSelect(self, query, match):
810 QueryExec(query, "SELECT calls.id, comm_id, thread_id"
811 " FROM calls"
812 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
813 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
814 " WHERE symbols.name" + match +
815 " ORDER BY comm_id, thread_id, call_time, calls.id")
816
817 def FindPath(self, query):
818 # Turn the query result into a list of ids that the tree view can walk
819 # to open the tree at the right place.
820 ids = []
821 parent_id = query.value(0)
822 while parent_id:
823 ids.insert(0, parent_id)
824 q2 = QSqlQuery(self.glb.db)
825 QueryExec(q2, "SELECT parent_id"
826 " FROM calls"
827 " WHERE id = " + str(parent_id))
828 if not q2.next():
829 break
830 parent_id = q2.value(0)
831 ids.insert(0, query.value(2))
832 ids.insert(0, query.value(1))
833 return ids
834
678# Vertical widget layout 835# Vertical widget layout
679 836
680class VBox(): 837class VBox():
@@ -693,28 +850,16 @@ class VBox():
693 def Widget(self): 850 def Widget(self):
694 return self.vbox 851 return self.vbox
695 852
696# Context-sensitive call graph window 853# Tree window base
697
698class CallGraphWindow(QMdiSubWindow):
699
700 def __init__(self, glb, parent=None):
701 super(CallGraphWindow, self).__init__(parent)
702
703 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
704
705 self.view = QTreeView()
706 self.view.setModel(self.model)
707
708 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
709 self.view.setColumnWidth(c, w)
710
711 self.find_bar = FindBar(self, self)
712 854
713 self.vbox = VBox(self.view, self.find_bar.Widget()) 855class TreeWindowBase(QMdiSubWindow):
714 856
715 self.setWidget(self.vbox.Widget()) 857 def __init__(self, parent=None):
858 super(TreeWindowBase, self).__init__(parent)
716 859
717 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") 860 self.model = None
861 self.view = None
862 self.find_bar = None
718 863
719 def DisplayFound(self, ids): 864 def DisplayFound(self, ids):
720 if not len(ids): 865 if not len(ids):
@@ -747,6 +892,53 @@ class CallGraphWindow(QMdiSubWindow):
747 if not found: 892 if not found:
748 self.find_bar.NotFound() 893 self.find_bar.NotFound()
749 894
895
896# Context-sensitive call graph window
897
898class CallGraphWindow(TreeWindowBase):
899
900 def __init__(self, glb, parent=None):
901 super(CallGraphWindow, self).__init__(parent)
902
903 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
904
905 self.view = QTreeView()
906 self.view.setModel(self.model)
907
908 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
909 self.view.setColumnWidth(c, w)
910
911 self.find_bar = FindBar(self, self)
912
913 self.vbox = VBox(self.view, self.find_bar.Widget())
914
915 self.setWidget(self.vbox.Widget())
916
917 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph")
918
919# Call tree window
920
921class CallTreeWindow(TreeWindowBase):
922
923 def __init__(self, glb, parent=None):
924 super(CallTreeWindow, self).__init__(parent)
925
926 self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x))
927
928 self.view = QTreeView()
929 self.view.setModel(self.model)
930
931 for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)):
932 self.view.setColumnWidth(c, w)
933
934 self.find_bar = FindBar(self, self)
935
936 self.vbox = VBox(self.view, self.find_bar.Widget())
937
938 self.setWidget(self.vbox.Widget())
939
940 AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree")
941
750# Child data item finder 942# Child data item finder
751 943
752class ChildDataItemFinder(): 944class ChildDataItemFinder():
@@ -1327,8 +1519,7 @@ class BranchModel(TreeModel):
1327 progress = Signal(object) 1519 progress = Signal(object)
1328 1520
1329 def __init__(self, glb, event_id, where_clause, parent=None): 1521 def __init__(self, glb, event_id, where_clause, parent=None):
1330 super(BranchModel, self).__init__(BranchRootItem(), parent) 1522 super(BranchModel, self).__init__(glb, parent)
1331 self.glb = glb
1332 self.event_id = event_id 1523 self.event_id = event_id
1333 self.more = True 1524 self.more = True
1334 self.populated = 0 1525 self.populated = 0
@@ -1352,6 +1543,9 @@ class BranchModel(TreeModel):
1352 self.fetcher.done.connect(self.Update) 1543 self.fetcher.done.connect(self.Update)
1353 self.fetcher.Fetch(glb_chunk_sz) 1544 self.fetcher.Fetch(glb_chunk_sz)
1354 1545
1546 def GetRoot(self):
1547 return BranchRootItem()
1548
1355 def columnCount(self, parent=None): 1549 def columnCount(self, parent=None):
1356 return 8 1550 return 8
1357 1551
@@ -1398,18 +1592,28 @@ class BranchModel(TreeModel):
1398 def HasMoreRecords(self): 1592 def HasMoreRecords(self):
1399 return self.more 1593 return self.more
1400 1594
1595# Report Variables
1596
1597class ReportVars():
1598
1599 def __init__(self, name = "", where_clause = "", limit = ""):
1600 self.name = name
1601 self.where_clause = where_clause
1602 self.limit = limit
1603
1604 def UniqueId(self):
1605 return str(self.where_clause + ";" + self.limit)
1606
1401# Branch window 1607# Branch window
1402 1608
1403class BranchWindow(QMdiSubWindow): 1609class BranchWindow(QMdiSubWindow):
1404 1610
1405 def __init__(self, glb, event_id, name, where_clause, parent=None): 1611 def __init__(self, glb, event_id, report_vars, parent=None):
1406 super(BranchWindow, self).__init__(parent) 1612 super(BranchWindow, self).__init__(parent)
1407 1613
1408 model_name = "Branch Events " + str(event_id) 1614 model_name = "Branch Events " + str(event_id) + " " + report_vars.UniqueId()
1409 if len(where_clause):
1410 model_name = where_clause + " " + model_name
1411 1615
1412 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, where_clause)) 1616 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, report_vars.where_clause))
1413 1617
1414 self.view = QTreeView() 1618 self.view = QTreeView()
1415 self.view.setUniformRowHeights(True) 1619 self.view.setUniformRowHeights(True)
@@ -1427,7 +1631,7 @@ class BranchWindow(QMdiSubWindow):
1427 1631
1428 self.setWidget(self.vbox.Widget()) 1632 self.setWidget(self.vbox.Widget())
1429 1633
1430 AddSubWindow(glb.mainwindow.mdi_area, self, name + " Branch Events") 1634 AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name + " Branch Events")
1431 1635
1432 def ResizeColumnToContents(self, column, n): 1636 def ResizeColumnToContents(self, column, n):
1433 # Using the view's resizeColumnToContents() here is extrememly slow 1637 # Using the view's resizeColumnToContents() here is extrememly slow
@@ -1472,47 +1676,134 @@ class BranchWindow(QMdiSubWindow):
1472 else: 1676 else:
1473 self.find_bar.NotFound() 1677 self.find_bar.NotFound()
1474 1678
1475# Dialog data item converted and validated using a SQL table 1679# Line edit data item
1476 1680
1477class SQLTableDialogDataItem(): 1681class LineEditDataItem(object):
1478 1682
1479 def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent): 1683 def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""):
1480 self.glb = glb 1684 self.glb = glb
1481 self.label = label 1685 self.label = label
1482 self.placeholder_text = placeholder_text 1686 self.placeholder_text = placeholder_text
1483 self.table_name = table_name
1484 self.match_column = match_column
1485 self.column_name1 = column_name1
1486 self.column_name2 = column_name2
1487 self.parent = parent 1687 self.parent = parent
1688 self.id = id
1488 1689
1489 self.value = "" 1690 self.value = default
1490 1691
1491 self.widget = QLineEdit() 1692 self.widget = QLineEdit(default)
1492 self.widget.editingFinished.connect(self.Validate) 1693 self.widget.editingFinished.connect(self.Validate)
1493 self.widget.textChanged.connect(self.Invalidate) 1694 self.widget.textChanged.connect(self.Invalidate)
1494 self.red = False 1695 self.red = False
1495 self.error = "" 1696 self.error = ""
1496 self.validated = True 1697 self.validated = True
1497 1698
1498 self.last_id = 0
1499 self.first_time = 0
1500 self.last_time = 2 ** 64
1501 if self.table_name == "<timeranges>":
1502 query = QSqlQuery(self.glb.db)
1503 QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1504 if query.next():
1505 self.last_id = int(query.value(0))
1506 self.last_time = int(query.value(1))
1507 QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1508 if query.next():
1509 self.first_time = int(query.value(0))
1510 if placeholder_text:
1511 placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1512
1513 if placeholder_text: 1699 if placeholder_text:
1514 self.widget.setPlaceholderText(placeholder_text) 1700 self.widget.setPlaceholderText(placeholder_text)
1515 1701
1702 def TurnTextRed(self):
1703 if not self.red:
1704 palette = QPalette()
1705 palette.setColor(QPalette.Text,Qt.red)
1706 self.widget.setPalette(palette)
1707 self.red = True
1708
1709 def TurnTextNormal(self):
1710 if self.red:
1711 palette = QPalette()
1712 self.widget.setPalette(palette)
1713 self.red = False
1714
1715 def InvalidValue(self, value):
1716 self.value = ""
1717 self.TurnTextRed()
1718 self.error = self.label + " invalid value '" + value + "'"
1719 self.parent.ShowMessage(self.error)
1720
1721 def Invalidate(self):
1722 self.validated = False
1723
1724 def DoValidate(self, input_string):
1725 self.value = input_string.strip()
1726
1727 def Validate(self):
1728 self.validated = True
1729 self.error = ""
1730 self.TurnTextNormal()
1731 self.parent.ClearMessage()
1732 input_string = self.widget.text()
1733 if not len(input_string.strip()):
1734 self.value = ""
1735 return
1736 self.DoValidate(input_string)
1737
1738 def IsValid(self):
1739 if not self.validated:
1740 self.Validate()
1741 if len(self.error):
1742 self.parent.ShowMessage(self.error)
1743 return False
1744 return True
1745
1746 def IsNumber(self, value):
1747 try:
1748 x = int(value)
1749 except:
1750 x = 0
1751 return str(x) == value
1752
1753# Non-negative integer ranges dialog data item
1754
1755class NonNegativeIntegerRangesDataItem(LineEditDataItem):
1756
1757 def __init__(self, glb, label, placeholder_text, column_name, parent):
1758 super(NonNegativeIntegerRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1759
1760 self.column_name = column_name
1761
1762 def DoValidate(self, input_string):
1763 singles = []
1764 ranges = []
1765 for value in [x.strip() for x in input_string.split(",")]:
1766 if "-" in value:
1767 vrange = value.split("-")
1768 if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1769 return self.InvalidValue(value)
1770 ranges.append(vrange)
1771 else:
1772 if not self.IsNumber(value):
1773 return self.InvalidValue(value)
1774 singles.append(value)
1775 ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1776 if len(singles):
1777 ranges.append(self.column_name + " IN (" + ",".join(singles) + ")")
1778 self.value = " OR ".join(ranges)
1779
1780# Positive integer dialog data item
1781
1782class PositiveIntegerDataItem(LineEditDataItem):
1783
1784 def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""):
1785 super(PositiveIntegerDataItem, self).__init__(glb, label, placeholder_text, parent, id, default)
1786
1787 def DoValidate(self, input_string):
1788 if not self.IsNumber(input_string.strip()):
1789 return self.InvalidValue(input_string)
1790 value = int(input_string.strip())
1791 if value <= 0:
1792 return self.InvalidValue(input_string)
1793 self.value = str(value)
1794
1795# Dialog data item converted and validated using a SQL table
1796
1797class SQLTableDataItem(LineEditDataItem):
1798
1799 def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent):
1800 super(SQLTableDataItem, self).__init__(glb, label, placeholder_text, parent)
1801
1802 self.table_name = table_name
1803 self.match_column = match_column
1804 self.column_name1 = column_name1
1805 self.column_name2 = column_name2
1806
1516 def ValueToIds(self, value): 1807 def ValueToIds(self, value):
1517 ids = [] 1808 ids = []
1518 query = QSqlQuery(self.glb.db) 1809 query = QSqlQuery(self.glb.db)
@@ -1523,6 +1814,42 @@ class SQLTableDialogDataItem():
1523 ids.append(str(query.value(0))) 1814 ids.append(str(query.value(0)))
1524 return ids 1815 return ids
1525 1816
1817 def DoValidate(self, input_string):
1818 all_ids = []
1819 for value in [x.strip() for x in input_string.split(",")]:
1820 ids = self.ValueToIds(value)
1821 if len(ids):
1822 all_ids.extend(ids)
1823 else:
1824 return self.InvalidValue(value)
1825 self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1826 if self.column_name2:
1827 self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1828
1829# Sample time ranges dialog data item converted and validated using 'samples' SQL table
1830
1831class SampleTimeRangesDataItem(LineEditDataItem):
1832
1833 def __init__(self, glb, label, placeholder_text, column_name, parent):
1834 self.column_name = column_name
1835
1836 self.last_id = 0
1837 self.first_time = 0
1838 self.last_time = 2 ** 64
1839
1840 query = QSqlQuery(glb.db)
1841 QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1842 if query.next():
1843 self.last_id = int(query.value(0))
1844 self.last_time = int(query.value(1))
1845 QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1846 if query.next():
1847 self.first_time = int(query.value(0))
1848 if placeholder_text:
1849 placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1850
1851 super(SampleTimeRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1852
1526 def IdBetween(self, query, lower_id, higher_id, order): 1853 def IdBetween(self, query, lower_id, higher_id, order):
1527 QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1") 1854 QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1")
1528 if query.next(): 1855 if query.next():
@@ -1560,7 +1887,6 @@ class SQLTableDialogDataItem():
1560 return str(lower_id) 1887 return str(lower_id)
1561 1888
1562 def ConvertRelativeTime(self, val): 1889 def ConvertRelativeTime(self, val):
1563 print "val ", val
1564 mult = 1 1890 mult = 1
1565 suffix = val[-2:] 1891 suffix = val[-2:]
1566 if suffix == "ms": 1892 if suffix == "ms":
@@ -1582,29 +1908,23 @@ class SQLTableDialogDataItem():
1582 return str(val) 1908 return str(val)
1583 1909
1584 def ConvertTimeRange(self, vrange): 1910 def ConvertTimeRange(self, vrange):
1585 print "vrange ", vrange
1586 if vrange[0] == "": 1911 if vrange[0] == "":
1587 vrange[0] = str(self.first_time) 1912 vrange[0] = str(self.first_time)
1588 if vrange[1] == "": 1913 if vrange[1] == "":
1589 vrange[1] = str(self.last_time) 1914 vrange[1] = str(self.last_time)
1590 vrange[0] = self.ConvertRelativeTime(vrange[0]) 1915 vrange[0] = self.ConvertRelativeTime(vrange[0])
1591 vrange[1] = self.ConvertRelativeTime(vrange[1]) 1916 vrange[1] = self.ConvertRelativeTime(vrange[1])
1592 print "vrange2 ", vrange
1593 if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): 1917 if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1594 return False 1918 return False
1595 print "ok1"
1596 beg_range = max(int(vrange[0]), self.first_time) 1919 beg_range = max(int(vrange[0]), self.first_time)
1597 end_range = min(int(vrange[1]), self.last_time) 1920 end_range = min(int(vrange[1]), self.last_time)
1598 if beg_range > self.last_time or end_range < self.first_time: 1921 if beg_range > self.last_time or end_range < self.first_time:
1599 return False 1922 return False
1600 print "ok2"
1601 vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True) 1923 vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True)
1602 vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False) 1924 vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False)
1603 print "vrange3 ", vrange
1604 return True 1925 return True
1605 1926
1606 def AddTimeRange(self, value, ranges): 1927 def AddTimeRange(self, value, ranges):
1607 print "value ", value
1608 n = value.count("-") 1928 n = value.count("-")
1609 if n == 1: 1929 if n == 1:
1610 pass 1930 pass
@@ -1622,111 +1942,31 @@ class SQLTableDialogDataItem():
1622 return True 1942 return True
1623 return False 1943 return False
1624 1944
1625 def InvalidValue(self, value): 1945 def DoValidate(self, input_string):
1626 self.value = "" 1946 ranges = []
1627 palette = QPalette() 1947 for value in [x.strip() for x in input_string.split(",")]:
1628 palette.setColor(QPalette.Text,Qt.red) 1948 if not self.AddTimeRange(value, ranges):
1629 self.widget.setPalette(palette) 1949 return self.InvalidValue(value)
1630 self.red = True 1950 ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1631 self.error = self.label + " invalid value '" + value + "'" 1951 self.value = " OR ".join(ranges)
1632 self.parent.ShowMessage(self.error)
1633
1634 def IsNumber(self, value):
1635 try:
1636 x = int(value)
1637 except:
1638 x = 0
1639 return str(x) == value
1640 1952
1641 def Invalidate(self): 1953# Report Dialog Base
1642 self.validated = False
1643 1954
1644 def Validate(self): 1955class ReportDialogBase(QDialog):
1645 input_string = self.widget.text()
1646 self.validated = True
1647 if self.red:
1648 palette = QPalette()
1649 self.widget.setPalette(palette)
1650 self.red = False
1651 if not len(input_string.strip()):
1652 self.error = ""
1653 self.value = ""
1654 return
1655 if self.table_name == "<timeranges>":
1656 ranges = []
1657 for value in [x.strip() for x in input_string.split(",")]:
1658 if not self.AddTimeRange(value, ranges):
1659 return self.InvalidValue(value)
1660 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1661 self.value = " OR ".join(ranges)
1662 elif self.table_name == "<ranges>":
1663 singles = []
1664 ranges = []
1665 for value in [x.strip() for x in input_string.split(",")]:
1666 if "-" in value:
1667 vrange = value.split("-")
1668 if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1669 return self.InvalidValue(value)
1670 ranges.append(vrange)
1671 else:
1672 if not self.IsNumber(value):
1673 return self.InvalidValue(value)
1674 singles.append(value)
1675 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1676 if len(singles):
1677 ranges.append(self.column_name1 + " IN (" + ",".join(singles) + ")")
1678 self.value = " OR ".join(ranges)
1679 elif self.table_name:
1680 all_ids = []
1681 for value in [x.strip() for x in input_string.split(",")]:
1682 ids = self.ValueToIds(value)
1683 if len(ids):
1684 all_ids.extend(ids)
1685 else:
1686 return self.InvalidValue(value)
1687 self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1688 if self.column_name2:
1689 self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1690 else:
1691 self.value = input_string.strip()
1692 self.error = ""
1693 self.parent.ClearMessage()
1694 1956
1695 def IsValid(self): 1957 def __init__(self, glb, title, items, partial, parent=None):
1696 if not self.validated: 1958 super(ReportDialogBase, self).__init__(parent)
1697 self.Validate()
1698 if len(self.error):
1699 self.parent.ShowMessage(self.error)
1700 return False
1701 return True
1702
1703# Selected branch report creation dialog
1704
1705class SelectedBranchDialog(QDialog):
1706
1707 def __init__(self, glb, parent=None):
1708 super(SelectedBranchDialog, self).__init__(parent)
1709 1959
1710 self.glb = glb 1960 self.glb = glb
1711 1961
1712 self.name = "" 1962 self.report_vars = ReportVars()
1713 self.where_clause = ""
1714 1963
1715 self.setWindowTitle("Selected Branches") 1964 self.setWindowTitle(title)
1716 self.setMinimumWidth(600) 1965 self.setMinimumWidth(600)
1717 1966
1718 items = ( 1967 self.data_items = [x(glb, self) for x in items]
1719 ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""), 1968
1720 ("Time ranges:", "Enter time ranges", "<timeranges>", "", "samples.id", ""), 1969 self.partial = partial
1721 ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "<ranges>", "", "cpu", ""),
1722 ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""),
1723 ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""),
1724 ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""),
1725 ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"),
1726 ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"),
1727 ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""),
1728 )
1729 self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items]
1730 1970
1731 self.grid = QGridLayout() 1971 self.grid = QGridLayout()
1732 1972
@@ -1758,23 +1998,28 @@ class SelectedBranchDialog(QDialog):
1758 self.setLayout(self.vbox); 1998 self.setLayout(self.vbox);
1759 1999
1760 def Ok(self): 2000 def Ok(self):
1761 self.name = self.data_items[0].value 2001 vars = self.report_vars
1762 if not self.name: 2002 for d in self.data_items:
2003 if d.id == "REPORTNAME":
2004 vars.name = d.value
2005 if not vars.name:
1763 self.ShowMessage("Report name is required") 2006 self.ShowMessage("Report name is required")
1764 return 2007 return
1765 for d in self.data_items: 2008 for d in self.data_items:
1766 if not d.IsValid(): 2009 if not d.IsValid():
1767 return 2010 return
1768 for d in self.data_items[1:]: 2011 for d in self.data_items[1:]:
1769 if len(d.value): 2012 if d.id == "LIMIT":
1770 if len(self.where_clause): 2013 vars.limit = d.value
1771 self.where_clause += " AND " 2014 elif len(d.value):
1772 self.where_clause += d.value 2015 if len(vars.where_clause):
1773 if len(self.where_clause): 2016 vars.where_clause += " AND "
1774 self.where_clause = " AND ( " + self.where_clause + " ) " 2017 vars.where_clause += d.value
1775 else: 2018 if len(vars.where_clause):
1776 self.ShowMessage("No selection") 2019 if self.partial:
1777 return 2020 vars.where_clause = " AND ( " + vars.where_clause + " ) "
2021 else:
2022 vars.where_clause = " WHERE " + vars.where_clause + " "
1778 self.accept() 2023 self.accept()
1779 2024
1780 def ShowMessage(self, msg): 2025 def ShowMessage(self, msg):
@@ -1783,6 +2028,23 @@ class SelectedBranchDialog(QDialog):
1783 def ClearMessage(self): 2028 def ClearMessage(self):
1784 self.status.setText("") 2029 self.status.setText("")
1785 2030
2031# Selected branch report creation dialog
2032
2033class SelectedBranchDialog(ReportDialogBase):
2034
2035 def __init__(self, glb, parent=None):
2036 title = "Selected Branches"
2037 items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"),
2038 lambda g, p: SampleTimeRangesDataItem(g, "Time ranges:", "Enter time ranges", "samples.id", p),
2039 lambda g, p: NonNegativeIntegerRangesDataItem(g, "CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "cpu", p),
2040 lambda g, p: SQLTableDataItem(g, "Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", "", p),
2041 lambda g, p: SQLTableDataItem(g, "PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", "", p),
2042 lambda g, p: SQLTableDataItem(g, "TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", "", p),
2043 lambda g, p: SQLTableDataItem(g, "DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id", p),
2044 lambda g, p: SQLTableDataItem(g, "Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id", p),
2045 lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p))
2046 super(SelectedBranchDialog, self).__init__(glb, title, items, True, parent)
2047
1786# Event list 2048# Event list
1787 2049
1788def GetEventList(db): 2050def GetEventList(db):
@@ -1793,6 +2055,16 @@ def GetEventList(db):
1793 events.append(query.value(0)) 2055 events.append(query.value(0))
1794 return events 2056 return events
1795 2057
2058# Is a table selectable
2059
2060def IsSelectable(db, table, sql = ""):
2061 query = QSqlQuery(db)
2062 try:
2063 QueryExec(query, "SELECT * FROM " + table + " " + sql + " LIMIT 1")
2064 except:
2065 return False
2066 return True
2067
1796# SQL data preparation 2068# SQL data preparation
1797 2069
1798def SQLTableDataPrep(query, count): 2070def SQLTableDataPrep(query, count):
@@ -1818,12 +2090,13 @@ class SQLTableModel(TableModel):
1818 2090
1819 progress = Signal(object) 2091 progress = Signal(object)
1820 2092
1821 def __init__(self, glb, sql, column_count, parent=None): 2093 def __init__(self, glb, sql, column_headers, parent=None):
1822 super(SQLTableModel, self).__init__(parent) 2094 super(SQLTableModel, self).__init__(parent)
1823 self.glb = glb 2095 self.glb = glb
1824 self.more = True 2096 self.more = True
1825 self.populated = 0 2097 self.populated = 0
1826 self.fetcher = SQLFetcher(glb, sql, lambda x, y=column_count: SQLTableDataPrep(x, y), self.AddSample) 2098 self.column_headers = column_headers
2099 self.fetcher = SQLFetcher(glb, sql, lambda x, y=len(column_headers): SQLTableDataPrep(x, y), self.AddSample)
1827 self.fetcher.done.connect(self.Update) 2100 self.fetcher.done.connect(self.Update)
1828 self.fetcher.Fetch(glb_chunk_sz) 2101 self.fetcher.Fetch(glb_chunk_sz)
1829 2102
@@ -1861,6 +2134,12 @@ class SQLTableModel(TableModel):
1861 def HasMoreRecords(self): 2134 def HasMoreRecords(self):
1862 return self.more 2135 return self.more
1863 2136
2137 def columnCount(self, parent=None):
2138 return len(self.column_headers)
2139
2140 def columnHeader(self, column):
2141 return self.column_headers[column]
2142
1864# SQL automatic table data model 2143# SQL automatic table data model
1865 2144
1866class SQLAutoTableModel(SQLTableModel): 2145class SQLAutoTableModel(SQLTableModel):
@@ -1870,12 +2149,12 @@ class SQLAutoTableModel(SQLTableModel):
1870 if table_name == "comm_threads_view": 2149 if table_name == "comm_threads_view":
1871 # For now, comm_threads_view has no id column 2150 # For now, comm_threads_view has no id column
1872 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz) 2151 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz)
1873 self.column_headers = [] 2152 column_headers = []
1874 query = QSqlQuery(glb.db) 2153 query = QSqlQuery(glb.db)
1875 if glb.dbref.is_sqlite3: 2154 if glb.dbref.is_sqlite3:
1876 QueryExec(query, "PRAGMA table_info(" + table_name + ")") 2155 QueryExec(query, "PRAGMA table_info(" + table_name + ")")
1877 while query.next(): 2156 while query.next():
1878 self.column_headers.append(query.value(1)) 2157 column_headers.append(query.value(1))
1879 if table_name == "sqlite_master": 2158 if table_name == "sqlite_master":
1880 sql = "SELECT * FROM " + table_name 2159 sql = "SELECT * FROM " + table_name
1881 else: 2160 else:
@@ -1888,14 +2167,8 @@ class SQLAutoTableModel(SQLTableModel):
1888 schema = "public" 2167 schema = "public"
1889 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'") 2168 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'")
1890 while query.next(): 2169 while query.next():
1891 self.column_headers.append(query.value(0)) 2170 column_headers.append(query.value(0))
1892 super(SQLAutoTableModel, self).__init__(glb, sql, len(self.column_headers), parent) 2171 super(SQLAutoTableModel, self).__init__(glb, sql, column_headers, parent)
1893
1894 def columnCount(self, parent=None):
1895 return len(self.column_headers)
1896
1897 def columnHeader(self, column):
1898 return self.column_headers[column]
1899 2172
1900# Base class for custom ResizeColumnsToContents 2173# Base class for custom ResizeColumnsToContents
1901 2174
@@ -1998,6 +2271,103 @@ def GetTableList(glb):
1998 tables.append("information_schema.columns") 2271 tables.append("information_schema.columns")
1999 return tables 2272 return tables
2000 2273
2274# Top Calls data model
2275
2276class TopCallsModel(SQLTableModel):
2277
2278 def __init__(self, glb, report_vars, parent=None):
2279 text = ""
2280 if not glb.dbref.is_sqlite3:
2281 text = "::text"
2282 limit = ""
2283 if len(report_vars.limit):
2284 limit = " LIMIT " + report_vars.limit
2285 sql = ("SELECT comm, pid, tid, name,"
2286 " CASE"
2287 " WHEN (short_name = '[kernel.kallsyms]') THEN '[kernel]'" + text +
2288 " ELSE short_name"
2289 " END AS dso,"
2290 " call_time, return_time, (return_time - call_time) AS elapsed_time, branch_count, "
2291 " CASE"
2292 " WHEN (calls.flags = 1) THEN 'no call'" + text +
2293 " WHEN (calls.flags = 2) THEN 'no return'" + text +
2294 " WHEN (calls.flags = 3) THEN 'no call/return'" + text +
2295 " ELSE ''" + text +
2296 " END AS flags"
2297 " FROM calls"
2298 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
2299 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
2300 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
2301 " INNER JOIN comms ON calls.comm_id = comms.id"
2302 " INNER JOIN threads ON calls.thread_id = threads.id" +
2303 report_vars.where_clause +
2304 " ORDER BY elapsed_time DESC" +
2305 limit
2306 )
2307 column_headers = ("Command", "PID", "TID", "Symbol", "Object", "Call Time", "Return Time", "Elapsed Time (ns)", "Branch Count", "Flags")
2308 self.alignment = (Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignLeft)
2309 super(TopCallsModel, self).__init__(glb, sql, column_headers, parent)
2310
2311 def columnAlignment(self, column):
2312 return self.alignment[column]
2313
2314# Top Calls report creation dialog
2315
2316class TopCallsDialog(ReportDialogBase):
2317
2318 def __init__(self, glb, parent=None):
2319 title = "Top Calls by Elapsed Time"
2320 items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"),
2321 lambda g, p: SQLTableDataItem(g, "Commands:", "Only calls with these commands will be included", "comms", "comm", "comm_id", "", p),
2322 lambda g, p: SQLTableDataItem(g, "PIDs:", "Only calls with these process IDs will be included", "threads", "pid", "thread_id", "", p),
2323 lambda g, p: SQLTableDataItem(g, "TIDs:", "Only calls with these thread IDs will be included", "threads", "tid", "thread_id", "", p),
2324 lambda g, p: SQLTableDataItem(g, "DSOs:", "Only calls with these DSOs will be included", "dsos", "short_name", "dso_id", "", p),
2325 lambda g, p: SQLTableDataItem(g, "Symbols:", "Only calls with these symbols will be included", "symbols", "name", "symbol_id", "", p),
2326 lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p),
2327 lambda g, p: PositiveIntegerDataItem(g, "Record limit:", "Limit selection to this number of records", p, "LIMIT", "100"))
2328 super(TopCallsDialog, self).__init__(glb, title, items, False, parent)
2329
2330# Top Calls window
2331
2332class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
2333
2334 def __init__(self, glb, report_vars, parent=None):
2335 super(TopCallsWindow, self).__init__(parent)
2336
2337 self.data_model = LookupCreateModel("Top Calls " + report_vars.UniqueId(), lambda: TopCallsModel(glb, report_vars))
2338 self.model = self.data_model
2339
2340 self.view = QTableView()
2341 self.view.setModel(self.model)
2342 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
2343 self.view.verticalHeader().setVisible(False)
2344
2345 self.ResizeColumnsToContents()
2346
2347 self.find_bar = FindBar(self, self, True)
2348
2349 self.finder = ChildDataItemFinder(self.model)
2350
2351 self.fetch_bar = FetchMoreRecordsBar(self.data_model, self)
2352
2353 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
2354
2355 self.setWidget(self.vbox.Widget())
2356
2357 AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name)
2358
2359 def Find(self, value, direction, pattern, context):
2360 self.view.setFocus()
2361 self.find_bar.Busy()
2362 self.finder.Find(value, direction, pattern, context, self.FindDone)
2363
2364 def FindDone(self, row):
2365 self.find_bar.Idle()
2366 if row >= 0:
2367 self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex()))
2368 else:
2369 self.find_bar.NotFound()
2370
2001# Action Definition 2371# Action Definition
2002 2372
2003def CreateAction(label, tip, callback, parent=None, shortcut=None): 2373def CreateAction(label, tip, callback, parent=None, shortcut=None):
@@ -2099,8 +2469,10 @@ p.c2 {
2099</style> 2469</style>
2100<p class=c1><a href=#reports>1. Reports</a></p> 2470<p class=c1><a href=#reports>1. Reports</a></p>
2101<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p> 2471<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p>
2102<p class=c2><a href=#allbranches>1.2 All branches</a></p> 2472<p class=c2><a href=#calltree>1.2 Call Tree</a></p>
2103<p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p> 2473<p class=c2><a href=#allbranches>1.3 All branches</a></p>
2474<p class=c2><a href=#selectedbranches>1.4 Selected branches</a></p>
2475<p class=c2><a href=#topcallsbyelapsedtime>1.5 Top calls by elapsed time</a></p>
2104<p class=c1><a href=#tables>2. Tables</a></p> 2476<p class=c1><a href=#tables>2. Tables</a></p>
2105<h1 id=reports>1. Reports</h1> 2477<h1 id=reports>1. Reports</h1>
2106<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2> 2478<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2>
@@ -2136,7 +2508,10 @@ v- ls
2136<h3>Find</h3> 2508<h3>Find</h3>
2137Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match. 2509Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match.
2138The pattern matching symbols are ? for any character and * for zero or more characters. 2510The pattern matching symbols are ? for any character and * for zero or more characters.
2139<h2 id=allbranches>1.2 All branches</h2> 2511<h2 id=calltree>1.2 Call Tree</h2>
2512The Call Tree report is very similar to the Context-Sensitive Call Graph, but the data is not aggregated.
2513Also the 'Count' column, which would be always 1, is replaced by the 'Call Time'.
2514<h2 id=allbranches>1.3 All branches</h2>
2140The All branches report displays all branches in chronological order. 2515The All branches report displays all branches in chronological order.
2141Not all data is fetched immediately. More records can be fetched using the Fetch bar provided. 2516Not all data is fetched immediately. More records can be fetched using the Fetch bar provided.
2142<h3>Disassembly</h3> 2517<h3>Disassembly</h3>
@@ -2162,10 +2537,10 @@ sudo ldconfig
2162Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. 2537Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.
2163Refer to Python documentation for the regular expression syntax. 2538Refer to Python documentation for the regular expression syntax.
2164All columns are searched, but only currently fetched rows are searched. 2539All columns are searched, but only currently fetched rows are searched.
2165<h2 id=selectedbranches>1.3 Selected branches</h2> 2540<h2 id=selectedbranches>1.4 Selected branches</h2>
2166This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced 2541This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced
2167by various selection criteria. A dialog box displays available criteria which are AND'ed together. 2542by various selection criteria. A dialog box displays available criteria which are AND'ed together.
2168<h3>1.3.1 Time ranges</h3> 2543<h3>1.4.1 Time ranges</h3>
2169The time ranges hint text shows the total time range. Relative time ranges can also be entered in 2544The time ranges hint text shows the total time range. Relative time ranges can also be entered in
2170ms, us or ns. Also, negative values are relative to the end of trace. Examples: 2545ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2171<pre> 2546<pre>
@@ -2176,6 +2551,10 @@ ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2176 -10ms- The last 10ms 2551 -10ms- The last 10ms
2177</pre> 2552</pre>
2178N.B. Due to the granularity of timestamps, there could be no branches in any given time range. 2553N.B. Due to the granularity of timestamps, there could be no branches in any given time range.
2554<h2 id=topcallsbyelapsedtime>1.5 Top calls by elapsed time</h2>
2555The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned.
2556The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together.
2557If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar.
2179<h1 id=tables>2. Tables</h1> 2558<h1 id=tables>2. Tables</h1>
2180The Tables menu shows all tables and views in the database. Most tables have an associated view 2559The Tables menu shows all tables and views in the database. Most tables have an associated view
2181which displays the information in a more friendly way. Not all data for large tables is fetched 2560which displays the information in a more friendly way. Not all data for large tables is fetched
@@ -2305,10 +2684,17 @@ class MainWindow(QMainWindow):
2305 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")])) 2684 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")]))
2306 2685
2307 reports_menu = menu.addMenu("&Reports") 2686 reports_menu = menu.addMenu("&Reports")
2308 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) 2687 if IsSelectable(glb.db, "calls"):
2688 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self))
2689
2690 if IsSelectable(glb.db, "calls", "WHERE parent_id >= 0"):
2691 reports_menu.addAction(CreateAction("Call &Tree", "Create a new window containing a call tree", self.NewCallTree, self))
2309 2692
2310 self.EventMenu(GetEventList(glb.db), reports_menu) 2693 self.EventMenu(GetEventList(glb.db), reports_menu)
2311 2694
2695 if IsSelectable(glb.db, "calls"):
2696 reports_menu.addAction(CreateAction("&Top calls by elapsed time", "Create a new window displaying top calls by elapsed time", self.NewTopCalls, self))
2697
2312 self.TableMenu(GetTableList(glb), menu) 2698 self.TableMenu(GetTableList(glb), menu)
2313 2699
2314 self.window_menu = WindowMenu(self.mdi_area, menu) 2700 self.window_menu = WindowMenu(self.mdi_area, menu)
@@ -2364,14 +2750,23 @@ class MainWindow(QMainWindow):
2364 def NewCallGraph(self): 2750 def NewCallGraph(self):
2365 CallGraphWindow(self.glb, self) 2751 CallGraphWindow(self.glb, self)
2366 2752
2753 def NewCallTree(self):
2754 CallTreeWindow(self.glb, self)
2755
2756 def NewTopCalls(self):
2757 dialog = TopCallsDialog(self.glb, self)
2758 ret = dialog.exec_()
2759 if ret:
2760 TopCallsWindow(self.glb, dialog.report_vars, self)
2761
2367 def NewBranchView(self, event_id): 2762 def NewBranchView(self, event_id):
2368 BranchWindow(self.glb, event_id, "", "", self) 2763 BranchWindow(self.glb, event_id, ReportVars(), self)
2369 2764
2370 def NewSelectedBranchView(self, event_id): 2765 def NewSelectedBranchView(self, event_id):
2371 dialog = SelectedBranchDialog(self.glb, self) 2766 dialog = SelectedBranchDialog(self.glb, self)
2372 ret = dialog.exec_() 2767 ret = dialog.exec_()
2373 if ret: 2768 if ret:
2374 BranchWindow(self.glb, event_id, dialog.name, dialog.where_clause, self) 2769 BranchWindow(self.glb, event_id, dialog.report_vars, self)
2375 2770
2376 def NewTableView(self, table_name): 2771 def NewTableView(self, table_name):
2377 TableWindow(self.glb, table_name, self) 2772 TableWindow(self.glb, table_name, self)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index cafeff3d74db..310efe5e7e23 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -5,6 +5,8 @@
5# Displays system-wide failed system call totals, broken down by pid. 5# Displays system-wide failed system call totals, broken down by pid.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os 10import os
9import sys 11import sys
10 12
@@ -32,7 +34,7 @@ if len(sys.argv) > 1:
32syscalls = autodict() 34syscalls = autodict()
33 35
34def trace_begin(): 36def trace_begin():
35 print "Press control+C to stop and show the summary" 37 print("Press control+C to stop and show the summary")
36 38
37def trace_end(): 39def trace_end():
38 print_error_totals() 40 print_error_totals()
@@ -56,23 +58,22 @@ def syscalls__sys_exit(event_name, context, common_cpu,
56 raw_syscalls__sys_exit(**locals()) 58 raw_syscalls__sys_exit(**locals())
57 59
58def print_error_totals(): 60def print_error_totals():
59 if for_comm is not None: 61 if for_comm is not None:
60 print "\nsyscall errors for %s:\n\n" % (for_comm), 62 print("\nsyscall errors for %s:\n" % (for_comm))
61 else: 63 else:
62 print "\nsyscall errors:\n\n", 64 print("\nsyscall errors:\n")
63 65
64 print "%-30s %10s\n" % ("comm [pid]", "count"), 66 print("%-30s %10s" % ("comm [pid]", "count"))
65 print "%-30s %10s\n" % ("------------------------------", \ 67 print("%-30s %10s" % ("------------------------------", "----------"))
66 "----------"), 68
67 69 comm_keys = syscalls.keys()
68 comm_keys = syscalls.keys() 70 for comm in comm_keys:
69 for comm in comm_keys: 71 pid_keys = syscalls[comm].keys()
70 pid_keys = syscalls[comm].keys() 72 for pid in pid_keys:
71 for pid in pid_keys: 73 print("\n%s [%d]" % (comm, pid))
72 print "\n%s [%d]\n" % (comm, pid), 74 id_keys = syscalls[comm][pid].keys()
73 id_keys = syscalls[comm][pid].keys() 75 for id in id_keys:
74 for id in id_keys: 76 print(" syscall: %-16s" % syscall_name(id))
75 print " syscall: %-16s\n" % syscall_name(id), 77 ret_keys = syscalls[comm][pid][id].keys()
76 ret_keys = syscalls[comm][pid][id].keys() 78 for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True):
77 for ret, val in sorted(syscalls[comm][pid][id].iteritems(), key = lambda(k, v): (v, k), reverse = True): 79 print(" err = %-20s %10d" % (strerror(ret), val))
78 print " err = %-20s %10d\n" % (strerror(ret), val),
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 0f5cf437b602..0c4841acf75d 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -10,6 +10,8 @@
10# 10#
11# Measures futex contention 11# Measures futex contention
12 12
13from __future__ import print_function
14
13import os, sys 15import os, sys
14sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 16sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15from Util import * 17from Util import *
@@ -33,18 +35,18 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
33 35
34def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, 36def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
35 nr, ret): 37 nr, ret):
36 if thread_blocktime.has_key(tid): 38 if tid in thread_blocktime:
37 elapsed = nsecs(s, ns) - thread_blocktime[tid] 39 elapsed = nsecs(s, ns) - thread_blocktime[tid]
38 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed) 40 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
39 del thread_blocktime[tid] 41 del thread_blocktime[tid]
40 del thread_thislock[tid] 42 del thread_thislock[tid]
41 43
42def trace_begin(): 44def trace_begin():
43 print "Press control+C to stop and show the summary" 45 print("Press control+C to stop and show the summary")
44 46
45def trace_end(): 47def trace_end():
46 for (tid, lock) in lock_waits: 48 for (tid, lock) in lock_waits:
47 min, max, avg, count = lock_waits[tid, lock] 49 min, max, avg, count = lock_waits[tid, lock]
48 print "%s[%d] lock %x contended %d times, %d avg ns" % \ 50 print("%s[%d] lock %x contended %d times, %d avg ns" %
49 (process_names[tid], tid, lock, count, avg) 51 (process_names[tid], tid, lock, count, avg))
50 52
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py
index b19172d673af..a73847c8f548 100644
--- a/tools/perf/scripts/python/intel-pt-events.py
+++ b/tools/perf/scripts/python/intel-pt-events.py
@@ -10,6 +10,8 @@
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details. 11# more details.
12 12
13from __future__ import print_function
14
13import os 15import os
14import sys 16import sys
15import struct 17import struct
@@ -22,34 +24,34 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
22#from Core import * 24#from Core import *
23 25
24def trace_begin(): 26def trace_begin():
25 print "Intel PT Power Events and PTWRITE" 27 print("Intel PT Power Events and PTWRITE")
26 28
27def trace_end(): 29def trace_end():
28 print "End" 30 print("End")
29 31
30def trace_unhandled(event_name, context, event_fields_dict): 32def trace_unhandled(event_name, context, event_fields_dict):
31 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 33 print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
32 34
33def print_ptwrite(raw_buf): 35def print_ptwrite(raw_buf):
34 data = struct.unpack_from("<IQ", raw_buf) 36 data = struct.unpack_from("<IQ", raw_buf)
35 flags = data[0] 37 flags = data[0]
36 payload = data[1] 38 payload = data[1]
37 exact_ip = flags & 1 39 exact_ip = flags & 1
38 print "IP: %u payload: %#x" % (exact_ip, payload), 40 print("IP: %u payload: %#x" % (exact_ip, payload), end=' ')
39 41
40def print_cbr(raw_buf): 42def print_cbr(raw_buf):
41 data = struct.unpack_from("<BBBBII", raw_buf) 43 data = struct.unpack_from("<BBBBII", raw_buf)
42 cbr = data[0] 44 cbr = data[0]
43 f = (data[4] + 500) / 1000 45 f = (data[4] + 500) / 1000
44 p = ((cbr * 1000 / data[2]) + 5) / 10 46 p = ((cbr * 1000 / data[2]) + 5) / 10
45 print "%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), 47 print("%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), end=' ')
46 48
47def print_mwait(raw_buf): 49def print_mwait(raw_buf):
48 data = struct.unpack_from("<IQ", raw_buf) 50 data = struct.unpack_from("<IQ", raw_buf)
49 payload = data[1] 51 payload = data[1]
50 hints = payload & 0xff 52 hints = payload & 0xff
51 extensions = (payload >> 32) & 0x3 53 extensions = (payload >> 32) & 0x3
52 print "hints: %#x extensions: %#x" % (hints, extensions), 54 print("hints: %#x extensions: %#x" % (hints, extensions), end=' ')
53 55
54def print_pwre(raw_buf): 56def print_pwre(raw_buf):
55 data = struct.unpack_from("<IQ", raw_buf) 57 data = struct.unpack_from("<IQ", raw_buf)
@@ -57,13 +59,14 @@ def print_pwre(raw_buf):
57 hw = (payload >> 7) & 1 59 hw = (payload >> 7) & 1
58 cstate = (payload >> 12) & 0xf 60 cstate = (payload >> 12) & 0xf
59 subcstate = (payload >> 8) & 0xf 61 subcstate = (payload >> 8) & 0xf
60 print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), 62 print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate),
63 end=' ')
61 64
62def print_exstop(raw_buf): 65def print_exstop(raw_buf):
63 data = struct.unpack_from("<I", raw_buf) 66 data = struct.unpack_from("<I", raw_buf)
64 flags = data[0] 67 flags = data[0]
65 exact_ip = flags & 1 68 exact_ip = flags & 1
66 print "IP: %u" % (exact_ip), 69 print("IP: %u" % (exact_ip), end=' ')
67 70
68def print_pwrx(raw_buf): 71def print_pwrx(raw_buf):
69 data = struct.unpack_from("<IQ", raw_buf) 72 data = struct.unpack_from("<IQ", raw_buf)
@@ -71,36 +74,39 @@ def print_pwrx(raw_buf):
71 deepest_cstate = payload & 0xf 74 deepest_cstate = payload & 0xf
72 last_cstate = (payload >> 4) & 0xf 75 last_cstate = (payload >> 4) & 0xf
73 wake_reason = (payload >> 8) & 0xf 76 wake_reason = (payload >> 8) & 0xf
74 print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason), 77 print("deepest cstate: %u last cstate: %u wake reason: %#x" %
78 (deepest_cstate, last_cstate, wake_reason), end=' ')
75 79
76def print_common_start(comm, sample, name): 80def print_common_start(comm, sample, name):
77 ts = sample["time"] 81 ts = sample["time"]
78 cpu = sample["cpu"] 82 cpu = sample["cpu"]
79 pid = sample["pid"] 83 pid = sample["pid"]
80 tid = sample["tid"] 84 tid = sample["tid"]
81 print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), 85 print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" %
86 (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name),
87 end=' ')
82 88
83def print_common_ip(sample, symbol, dso): 89def print_common_ip(sample, symbol, dso):
84 ip = sample["ip"] 90 ip = sample["ip"]
85 print "%16x %s (%s)" % (ip, symbol, dso) 91 print("%16x %s (%s)" % (ip, symbol, dso))
86 92
87def process_event(param_dict): 93def process_event(param_dict):
88 event_attr = param_dict["attr"] 94 event_attr = param_dict["attr"]
89 sample = param_dict["sample"] 95 sample = param_dict["sample"]
90 raw_buf = param_dict["raw_buf"] 96 raw_buf = param_dict["raw_buf"]
91 comm = param_dict["comm"] 97 comm = param_dict["comm"]
92 name = param_dict["ev_name"] 98 name = param_dict["ev_name"]
93 99
94 # Symbol and dso info are not always resolved 100 # Symbol and dso info are not always resolved
95 if (param_dict.has_key("dso")): 101 if "dso" in param_dict:
96 dso = param_dict["dso"] 102 dso = param_dict["dso"]
97 else: 103 else:
98 dso = "[unknown]" 104 dso = "[unknown]"
99 105
100 if (param_dict.has_key("symbol")): 106 if "symbol" in param_dict:
101 symbol = param_dict["symbol"] 107 symbol = param_dict["symbol"]
102 else: 108 else:
103 symbol = "[unknown]" 109 symbol = "[unknown]"
104 110
105 if name == "ptwrite": 111 if name == "ptwrite":
106 print_common_start(comm, sample, name) 112 print_common_start(comm, sample, name)
diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py
index ebee2c5ae496..1f332e72b9b0 100644
--- a/tools/perf/scripts/python/mem-phys-addr.py
+++ b/tools/perf/scripts/python/mem-phys-addr.py
@@ -4,6 +4,8 @@
4# Copyright (c) 2018, Intel Corporation. 4# Copyright (c) 2018, Intel Corporation.
5 5
6from __future__ import division 6from __future__ import division
7from __future__ import print_function
8
7import os 9import os
8import sys 10import sys
9import struct 11import struct
@@ -31,21 +33,24 @@ def parse_iomem():
31 for i, j in enumerate(f): 33 for i, j in enumerate(f):
32 m = re.split('-|:',j,2) 34 m = re.split('-|:',j,2)
33 if m[2].strip() == 'System RAM': 35 if m[2].strip() == 'System RAM':
34 system_ram.append(long(m[0], 16)) 36 system_ram.append(int(m[0], 16))
35 system_ram.append(long(m[1], 16)) 37 system_ram.append(int(m[1], 16))
36 if m[2].strip() == 'Persistent Memory': 38 if m[2].strip() == 'Persistent Memory':
37 pmem.append(long(m[0], 16)) 39 pmem.append(int(m[0], 16))
38 pmem.append(long(m[1], 16)) 40 pmem.append(int(m[1], 16))
39 41
40def print_memory_type(): 42def print_memory_type():
41 print "Event: %s" % (event_name) 43 print("Event: %s" % (event_name))
42 print "%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), 44 print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='')
43 print "%-40s %10s %10s\n" % ("----------------------------------------", \ 45 print("%-40s %10s %10s\n" % ("----------------------------------------",
44 "-----------", "-----------"), 46 "-----------", "-----------"),
47 end='');
45 total = sum(load_mem_type_cnt.values()) 48 total = sum(load_mem_type_cnt.values())
46 for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ 49 for mem_type, count in sorted(load_mem_type_cnt.most_common(), \
47 key = lambda(k, v): (v, k), reverse = True): 50 key = lambda kv: (kv[1], kv[0]), reverse = True):
48 print "%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), 51 print("%-40s %10d %10.1f%%\n" %
52 (mem_type, count, 100 * count / total),
53 end='')
49 54
50def trace_begin(): 55def trace_begin():
51 parse_iomem() 56 parse_iomem()
@@ -80,7 +85,7 @@ def find_memory_type(phys_addr):
80 f.seek(0, 0) 85 f.seek(0, 0)
81 for j in f: 86 for j in f:
82 m = re.split('-|:',j,2) 87 m = re.split('-|:',j,2)
83 if long(m[0], 16) <= phys_addr <= long(m[1], 16): 88 if int(m[0], 16) <= phys_addr <= int(m[1], 16):
84 return m[2] 89 return m[2]
85 return "N/A" 90 return "N/A"
86 91
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index a150164b44a3..101059971738 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -1,11 +1,13 @@
1# Monitor the system for dropped packets and proudce a report of drop locations and counts 1# Monitor the system for dropped packets and proudce a report of drop locations and counts
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3 3
4from __future__ import print_function
5
4import os 6import os
5import sys 7import sys
6 8
7sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 9sys.path.append(os.environ['PERF_EXEC_PATH'] + \
8 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 10 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
9 11
10from perf_trace_context import * 12from perf_trace_context import *
11from Core import * 13from Core import *
@@ -50,19 +52,19 @@ def get_sym(sloc):
50 return (None, 0) 52 return (None, 0)
51 53
52def print_drop_table(): 54def print_drop_table():
53 print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT") 55 print("%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT"))
54 for i in drop_log.keys(): 56 for i in drop_log.keys():
55 (sym, off) = get_sym(i) 57 (sym, off) = get_sym(i)
56 if sym == None: 58 if sym == None:
57 sym = i 59 sym = i
58 print "%25s %25s %25s" % (sym, off, drop_log[i]) 60 print("%25s %25s %25s" % (sym, off, drop_log[i]))
59 61
60 62
61def trace_begin(): 63def trace_begin():
62 print "Starting trace (Ctrl-C to dump results)" 64 print("Starting trace (Ctrl-C to dump results)")
63 65
64def trace_end(): 66def trace_end():
65 print "Gathering kallsyms data" 67 print("Gathering kallsyms data")
66 get_kallsyms_table() 68 get_kallsyms_table()
67 print_drop_table() 69 print_drop_table()
68 70
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9b2050f778f1..ea0c8b90a783 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -8,6 +8,8 @@
8# dev=: show only thing related to specified device 8# dev=: show only thing related to specified device
9# debug: work with debug mode. It shows buffer status. 9# debug: work with debug mode. It shows buffer status.
10 10
11from __future__ import print_function
12
11import os 13import os
12import sys 14import sys
13 15
@@ -17,6 +19,7 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
17from perf_trace_context import * 19from perf_trace_context import *
18from Core import * 20from Core import *
19from Util import * 21from Util import *
22from functools import cmp_to_key
20 23
21all_event_list = []; # insert all tracepoint event related with this script 24all_event_list = []; # insert all tracepoint event related with this script
22irq_dic = {}; # key is cpu and value is a list which stacks irqs 25irq_dic = {}; # key is cpu and value is a list which stacks irqs
@@ -61,12 +64,12 @@ def diff_msec(src, dst):
61def print_transmit(hunk): 64def print_transmit(hunk):
62 if dev != 0 and hunk['dev'].find(dev) < 0: 65 if dev != 0 and hunk['dev'].find(dev) < 0:
63 return 66 return
64 print "%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % \ 67 print("%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" %
65 (hunk['dev'], hunk['len'], 68 (hunk['dev'], hunk['len'],
66 nsecs_secs(hunk['queue_t']), 69 nsecs_secs(hunk['queue_t']),
67 nsecs_nsecs(hunk['queue_t'])/1000, 70 nsecs_nsecs(hunk['queue_t'])/1000,
68 diff_msec(hunk['queue_t'], hunk['xmit_t']), 71 diff_msec(hunk['queue_t'], hunk['xmit_t']),
69 diff_msec(hunk['xmit_t'], hunk['free_t'])) 72 diff_msec(hunk['xmit_t'], hunk['free_t'])))
70 73
71# Format for displaying rx packet processing 74# Format for displaying rx packet processing
72PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)" 75PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)"
@@ -98,55 +101,57 @@ def print_receive(hunk):
98 if show_hunk == 0: 101 if show_hunk == 0:
99 return 102 return
100 103
101 print "%d.%06dsec cpu=%d" % \ 104 print("%d.%06dsec cpu=%d" %
102 (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu) 105 (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu))
103 for i in range(len(irq_list)): 106 for i in range(len(irq_list)):
104 print PF_IRQ_ENTRY % \ 107 print(PF_IRQ_ENTRY %
105 (diff_msec(base_t, irq_list[i]['irq_ent_t']), 108 (diff_msec(base_t, irq_list[i]['irq_ent_t']),
106 irq_list[i]['irq'], irq_list[i]['name']) 109 irq_list[i]['irq'], irq_list[i]['name']))
107 print PF_JOINT 110 print(PF_JOINT)
108 irq_event_list = irq_list[i]['event_list'] 111 irq_event_list = irq_list[i]['event_list']
109 for j in range(len(irq_event_list)): 112 for j in range(len(irq_event_list)):
110 irq_event = irq_event_list[j] 113 irq_event = irq_event_list[j]
111 if irq_event['event'] == 'netif_rx': 114 if irq_event['event'] == 'netif_rx':
112 print PF_NET_RX % \ 115 print(PF_NET_RX %
113 (diff_msec(base_t, irq_event['time']), 116 (diff_msec(base_t, irq_event['time']),
114 irq_event['skbaddr']) 117 irq_event['skbaddr']))
115 print PF_JOINT 118 print(PF_JOINT)
116 print PF_SOFT_ENTRY % \ 119 print(PF_SOFT_ENTRY %
117 diff_msec(base_t, hunk['sirq_ent_t']) 120 diff_msec(base_t, hunk['sirq_ent_t']))
118 print PF_JOINT 121 print(PF_JOINT)
119 event_list = hunk['event_list'] 122 event_list = hunk['event_list']
120 for i in range(len(event_list)): 123 for i in range(len(event_list)):
121 event = event_list[i] 124 event = event_list[i]
122 if event['event_name'] == 'napi_poll': 125 if event['event_name'] == 'napi_poll':
123 print PF_NAPI_POLL % \ 126 print(PF_NAPI_POLL %
124 (diff_msec(base_t, event['event_t']), event['dev']) 127 (diff_msec(base_t, event['event_t']),
128 event['dev']))
125 if i == len(event_list) - 1: 129 if i == len(event_list) - 1:
126 print "" 130 print("")
127 else: 131 else:
128 print PF_JOINT 132 print(PF_JOINT)
129 else: 133 else:
130 print PF_NET_RECV % \ 134 print(PF_NET_RECV %
131 (diff_msec(base_t, event['event_t']), event['skbaddr'], 135 (diff_msec(base_t, event['event_t']),
132 event['len']) 136 event['skbaddr'],
137 event['len']))
133 if 'comm' in event.keys(): 138 if 'comm' in event.keys():
134 print PF_WJOINT 139 print(PF_WJOINT)
135 print PF_CPY_DGRAM % \ 140 print(PF_CPY_DGRAM %
136 (diff_msec(base_t, event['comm_t']), 141 (diff_msec(base_t, event['comm_t']),
137 event['pid'], event['comm']) 142 event['pid'], event['comm']))
138 elif 'handle' in event.keys(): 143 elif 'handle' in event.keys():
139 print PF_WJOINT 144 print(PF_WJOINT)
140 if event['handle'] == "kfree_skb": 145 if event['handle'] == "kfree_skb":
141 print PF_KFREE_SKB % \ 146 print(PF_KFREE_SKB %
142 (diff_msec(base_t, 147 (diff_msec(base_t,
143 event['comm_t']), 148 event['comm_t']),
144 event['location']) 149 event['location']))
145 elif event['handle'] == "consume_skb": 150 elif event['handle'] == "consume_skb":
146 print PF_CONS_SKB % \ 151 print(PF_CONS_SKB %
147 diff_msec(base_t, 152 diff_msec(base_t,
148 event['comm_t']) 153 event['comm_t']))
149 print PF_JOINT 154 print(PF_JOINT)
150 155
151def trace_begin(): 156def trace_begin():
152 global show_tx 157 global show_tx
@@ -172,8 +177,7 @@ def trace_begin():
172 177
173def trace_end(): 178def trace_end():
174 # order all events in time 179 # order all events in time
175 all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME], 180 all_event_list.sort(key=cmp_to_key(lambda a,b :a[EINFO_IDX_TIME] < b[EINFO_IDX_TIME]))
176 b[EINFO_IDX_TIME]))
177 # process all events 181 # process all events
178 for i in range(len(all_event_list)): 182 for i in range(len(all_event_list)):
179 event_info = all_event_list[i] 183 event_info = all_event_list[i]
@@ -210,19 +214,19 @@ def trace_end():
210 print_receive(receive_hunk_list[i]) 214 print_receive(receive_hunk_list[i])
211 # display transmit hunks 215 # display transmit hunks
212 if show_tx: 216 if show_tx:
213 print " dev len Qdisc " \ 217 print(" dev len Qdisc "
214 " netdevice free" 218 " netdevice free")
215 for i in range(len(tx_free_list)): 219 for i in range(len(tx_free_list)):
216 print_transmit(tx_free_list[i]) 220 print_transmit(tx_free_list[i])
217 if debug: 221 if debug:
218 print "debug buffer status" 222 print("debug buffer status")
219 print "----------------------------" 223 print("----------------------------")
220 print "xmit Qdisc:remain:%d overflow:%d" % \ 224 print("xmit Qdisc:remain:%d overflow:%d" %
221 (len(tx_queue_list), of_count_tx_queue_list) 225 (len(tx_queue_list), of_count_tx_queue_list))
222 print "xmit netdevice:remain:%d overflow:%d" % \ 226 print("xmit netdevice:remain:%d overflow:%d" %
223 (len(tx_xmit_list), of_count_tx_xmit_list) 227 (len(tx_xmit_list), of_count_tx_xmit_list))
224 print "receive:remain:%d overflow:%d" % \ 228 print("receive:remain:%d overflow:%d" %
225 (len(rx_skb_list), of_count_rx_skb_list) 229 (len(rx_skb_list), of_count_rx_skb_list))
226 230
227# called from perf, when it finds a correspoinding event 231# called from perf, when it finds a correspoinding event
228def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec): 232def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
@@ -254,7 +258,7 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i
254 all_event_list.append(event_info) 258 all_event_list.append(event_info)
255 259
256def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, 260def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi,
257 dev_name, work=None, budget=None): 261 dev_name, work=None, budget=None):
258 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
259 napi, dev_name, work, budget) 263 napi, dev_name, work, budget)
260 all_event_list.append(event_info) 264 all_event_list.append(event_info)
@@ -351,7 +355,7 @@ def handle_irq_softirq_exit(event_info):
351 if irq_list == [] or event_list == 0: 355 if irq_list == [] or event_list == 0:
352 return 356 return
353 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time, 357 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
354 'irq_list':irq_list, 'event_list':event_list} 358 'irq_list':irq_list, 'event_list':event_list}
355 # merge information realted to a NET_RX softirq 359 # merge information realted to a NET_RX softirq
356 receive_hunk_list.append(rec_data) 360 receive_hunk_list.append(rec_data)
357 361
@@ -388,7 +392,7 @@ def handle_netif_receive_skb(event_info):
388 skbaddr, skblen, dev_name) = event_info 392 skbaddr, skblen, dev_name) = event_info
389 if cpu in net_rx_dic.keys(): 393 if cpu in net_rx_dic.keys():
390 rec_data = {'event_name':'netif_receive_skb', 394 rec_data = {'event_name':'netif_receive_skb',
391 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} 395 'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
392 event_list = net_rx_dic[cpu]['event_list'] 396 event_list = net_rx_dic[cpu]['event_list']
393 event_list.append(rec_data) 397 event_list.append(rec_data)
394 rx_skb_list.insert(0, rec_data) 398 rx_skb_list.insert(0, rec_data)
diff --git a/tools/perf/scripts/python/powerpc-hcalls.py b/tools/perf/scripts/python/powerpc-hcalls.py
index 00e0e7476e55..8b78dc790adb 100644
--- a/tools/perf/scripts/python/powerpc-hcalls.py
+++ b/tools/perf/scripts/python/powerpc-hcalls.py
@@ -4,6 +4,8 @@
4# 4#
5# Hypervisor call statisics 5# Hypervisor call statisics
6 6
7from __future__ import print_function
8
7import os 9import os
8import sys 10import sys
9 11
@@ -149,7 +151,7 @@ hcall_table = {
149} 151}
150 152
151def hcall_table_lookup(opcode): 153def hcall_table_lookup(opcode):
152 if (hcall_table.has_key(opcode)): 154 if (opcode in hcall_table):
153 return hcall_table[opcode] 155 return hcall_table[opcode]
154 else: 156 else:
155 return opcode 157 return opcode
@@ -157,8 +159,8 @@ def hcall_table_lookup(opcode):
157print_ptrn = '%-28s%10s%10s%10s%10s' 159print_ptrn = '%-28s%10s%10s%10s%10s'
158 160
159def trace_end(): 161def trace_end():
160 print print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)') 162 print(print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)'))
161 print '-' * 68 163 print('-' * 68)
162 for opcode in output: 164 for opcode in output:
163 h_name = hcall_table_lookup(opcode) 165 h_name = hcall_table_lookup(opcode)
164 time = output[opcode]['time'] 166 time = output[opcode]['time']
@@ -166,14 +168,14 @@ def trace_end():
166 min_t = output[opcode]['min'] 168 min_t = output[opcode]['min']
167 max_t = output[opcode]['max'] 169 max_t = output[opcode]['max']
168 170
169 print print_ptrn % (h_name, cnt, min_t, max_t, time/cnt) 171 print(print_ptrn % (h_name, cnt, min_t, max_t, time//cnt))
170 172
171def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain, 173def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
172 opcode, retval): 174 opcode, retval):
173 if (d_enter.has_key(cpu) and d_enter[cpu].has_key(opcode)): 175 if (cpu in d_enter and opcode in d_enter[cpu]):
174 diff = nsecs(sec, nsec) - d_enter[cpu][opcode] 176 diff = nsecs(sec, nsec) - d_enter[cpu][opcode]
175 177
176 if (output.has_key(opcode)): 178 if (opcode in output):
177 output[opcode]['time'] += diff 179 output[opcode]['time'] += diff
178 output[opcode]['cnt'] += 1 180 output[opcode]['cnt'] += 1
179 if (output[opcode]['min'] > diff): 181 if (output[opcode]['min'] > diff):
@@ -190,11 +192,11 @@ def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
190 192
191 del d_enter[cpu][opcode] 193 del d_enter[cpu][opcode]
192# else: 194# else:
193# print "Can't find matching hcall_enter event. Ignoring sample" 195# print("Can't find matching hcall_enter event. Ignoring sample")
194 196
195def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm, 197def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm,
196 callchain, opcode): 198 callchain, opcode):
197 if (d_enter.has_key(cpu)): 199 if (cpu in d_enter):
198 d_enter[cpu][opcode] = nsecs(sec, nsec) 200 d_enter[cpu][opcode] = nsecs(sec, nsec)
199 else: 201 else:
200 d_enter[cpu] = {opcode: nsecs(sec, nsec)} 202 d_enter[cpu] = {opcode: nsecs(sec, nsec)}
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 3473e7f66081..8196e3087c9e 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -1,5 +1,3 @@
1#!/usr/bin/python
2#
3# Cpu task migration overview toy 1# Cpu task migration overview toy
4# 2#
5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com> 3# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
@@ -16,10 +14,10 @@ import sys
16 14
17from collections import defaultdict 15from collections import defaultdict
18try: 16try:
19 from UserList import UserList 17 from UserList import UserList
20except ImportError: 18except ImportError:
21 # Python 3: UserList moved to the collections package 19 # Python 3: UserList moved to the collections package
22 from collections import UserList 20 from collections import UserList
23 21
24sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 22sys.path.append(os.environ['PERF_EXEC_PATH'] + \
25 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 23 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 61621b93affb..6e0278dcb092 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -8,7 +8,14 @@
8# will be refreshed every [interval] seconds. The default interval is 8# will be refreshed every [interval] seconds. The default interval is
9# 3 seconds. 9# 3 seconds.
10 10
11import os, sys, thread, time 11from __future__ import print_function
12
13import os, sys, time
14
15try:
16 import thread
17except ImportError:
18 import _thread as thread
12 19
13sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 20sys.path.append(os.environ['PERF_EXEC_PATH'] + \
14 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
@@ -62,18 +69,20 @@ def print_syscall_totals(interval):
62 while 1: 69 while 1:
63 clear_term() 70 clear_term()
64 if for_comm is not None: 71 if for_comm is not None:
65 print "\nsyscall events for %s:\n\n" % (for_comm), 72 print("\nsyscall events for %s:\n" % (for_comm))
66 else: 73 else:
67 print "\nsyscall events:\n\n", 74 print("\nsyscall events:\n")
68 75
69 print "%-40s %10s\n" % ("event", "count"), 76 print("%-40s %10s" % ("event", "count"))
70 print "%-40s %10s\n" % ("----------------------------------------", \ 77 print("%-40s %10s" %
71 "----------"), 78 ("----------------------------------------",
79 "----------"))
72 80
73 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ 81 for id, val in sorted(syscalls.items(),
74 reverse = True): 82 key = lambda kv: (kv[1], kv[0]),
83 reverse = True):
75 try: 84 try:
76 print "%-40s %10d\n" % (syscall_name(id), val), 85 print("%-40s %10d" % (syscall_name(id), val))
77 except TypeError: 86 except TypeError:
78 pass 87 pass
79 syscalls.clear() 88 syscalls.clear()
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
index 1697b5e18c96..b1c4def1410a 100755
--- a/tools/perf/scripts/python/stackcollapse.py
+++ b/tools/perf/scripts/python/stackcollapse.py
@@ -19,13 +19,15 @@
19# Written by Paolo Bonzini <pbonzini@redhat.com> 19# Written by Paolo Bonzini <pbonzini@redhat.com>
20# Based on Brendan Gregg's stackcollapse-perf.pl script. 20# Based on Brendan Gregg's stackcollapse-perf.pl script.
21 21
22from __future__ import print_function
23
22import os 24import os
23import sys 25import sys
24from collections import defaultdict 26from collections import defaultdict
25from optparse import OptionParser, make_option 27from optparse import OptionParser, make_option
26 28
27sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 29sys.path.append(os.environ['PERF_EXEC_PATH'] + \
28 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 30 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
29 31
30from perf_trace_context import * 32from perf_trace_context import *
31from Core import * 33from Core import *
@@ -120,7 +122,6 @@ def process_event(param_dict):
120 lines[stack_string] = lines[stack_string] + 1 122 lines[stack_string] = lines[stack_string] + 1
121 123
122def trace_end(): 124def trace_end():
123 list = lines.keys() 125 list = sorted(lines)
124 list.sort()
125 for stack in list: 126 for stack in list:
126 print "%s %d" % (stack, lines[stack]) 127 print("%s %d" % (stack, lines[stack]))
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
index 8410672efb8b..01fa933ff3cf 100644
--- a/tools/perf/scripts/python/stat-cpi.py
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -1,6 +1,7 @@
1#!/usr/bin/env python
2# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
3 2
3from __future__ import print_function
4
4data = {} 5data = {}
5times = [] 6times = []
6threads = [] 7threads = []
@@ -20,8 +21,8 @@ def store_key(time, cpu, thread):
20 threads.append(thread) 21 threads.append(thread)
21 22
22def store(time, event, cpu, thread, val, ena, run): 23def store(time, event, cpu, thread, val, ena, run):
23 #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \ 24 #print("event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" %
24 # (event, cpu, thread, time, val, ena, run) 25 # (event, cpu, thread, time, val, ena, run))
25 26
26 store_key(time, cpu, thread) 27 store_key(time, cpu, thread)
27 key = get_key(time, event, cpu, thread) 28 key = get_key(time, event, cpu, thread)
@@ -59,7 +60,7 @@ def stat__interval(time):
59 if ins != 0: 60 if ins != 0:
60 cpi = cyc/float(ins) 61 cpi = cyc/float(ins)
61 62
62 print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins) 63 print("%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins))
63 64
64def trace_end(): 65def trace_end():
65 pass 66 pass
@@ -75,4 +76,4 @@ def trace_end():
75# if ins != 0: 76# if ins != 0:
76# cpi = cyc/float(ins) 77# cpi = cyc/float(ins)
77# 78#
78# print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi) 79# print("time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi))
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index daf314cc5dd3..f254e40c6f0f 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -5,6 +5,8 @@
5# Displays system-wide system call totals, broken down by syscall. 5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os, sys 10import os, sys
9 11
10sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 12sys.path.append(os.environ['PERF_EXEC_PATH'] + \
@@ -31,17 +33,16 @@ if len(sys.argv) > 1:
31syscalls = autodict() 33syscalls = autodict()
32 34
33def trace_begin(): 35def trace_begin():
34 print "Press control+C to stop and show the summary" 36 print("Press control+C to stop and show the summary")
35 37
36def trace_end(): 38def trace_end():
37 print_syscall_totals() 39 print_syscall_totals()
38 40
39def raw_syscalls__sys_enter(event_name, context, common_cpu, 41def raw_syscalls__sys_enter(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm, 42 common_secs, common_nsecs, common_pid, common_comm,
41 common_callchain, id, args): 43 common_callchain, id, args):
42
43 if (for_comm and common_comm != for_comm) or \ 44 if (for_comm and common_comm != for_comm) or \
44 (for_pid and common_pid != for_pid ): 45 (for_pid and common_pid != for_pid ):
45 return 46 return
46 try: 47 try:
47 syscalls[common_comm][common_pid][id] += 1 48 syscalls[common_comm][common_pid][id] += 1
@@ -49,26 +50,26 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
49 syscalls[common_comm][common_pid][id] = 1 50 syscalls[common_comm][common_pid][id] = 1
50 51
51def syscalls__sys_enter(event_name, context, common_cpu, 52def syscalls__sys_enter(event_name, context, common_cpu,
52 common_secs, common_nsecs, common_pid, common_comm, 53 common_secs, common_nsecs, common_pid, common_comm,
53 id, args): 54 id, args):
54 raw_syscalls__sys_enter(**locals()) 55 raw_syscalls__sys_enter(**locals())
55 56
56def print_syscall_totals(): 57def print_syscall_totals():
57 if for_comm is not None: 58 if for_comm is not None:
58 print "\nsyscall events for %s:\n\n" % (for_comm), 59 print("\nsyscall events for %s:\n" % (for_comm))
59 else: 60 else:
60 print "\nsyscall events by comm/pid:\n\n", 61 print("\nsyscall events by comm/pid:\n")
61 62
62 print "%-40s %10s\n" % ("comm [pid]/syscalls", "count"), 63 print("%-40s %10s" % ("comm [pid]/syscalls", "count"))
63 print "%-40s %10s\n" % ("----------------------------------------", \ 64 print("%-40s %10s" % ("----------------------------------------",
64 "----------"), 65 "----------"))
65 66
66 comm_keys = syscalls.keys() 67 comm_keys = syscalls.keys()
67 for comm in comm_keys: 68 for comm in comm_keys:
68 pid_keys = syscalls[comm].keys() 69 pid_keys = syscalls[comm].keys()
69 for pid in pid_keys: 70 for pid in pid_keys:
70 print "\n%s [%d]\n" % (comm, pid), 71 print("\n%s [%d]" % (comm, pid))
71 id_keys = syscalls[comm][pid].keys() 72 id_keys = syscalls[comm][pid].keys()
72 for id, val in sorted(syscalls[comm][pid].iteritems(), \ 73 for id, val in sorted(syscalls[comm][pid].items(),
73 key = lambda(k, v): (v, k), reverse = True): 74 key = lambda kv: (kv[1], kv[0]), reverse = True):
74 print " %-38s %10d\n" % (syscall_name(id), val), 75 print(" %-38s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index e66a7730aeb5..8adb95ff1664 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -5,6 +5,8 @@
5# Displays system-wide system call totals, broken down by syscall. 5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os 10import os
9import sys 11import sys
10 12
@@ -28,14 +30,14 @@ if len(sys.argv) > 1:
28syscalls = autodict() 30syscalls = autodict()
29 31
30def trace_begin(): 32def trace_begin():
31 print "Press control+C to stop and show the summary" 33 print("Press control+C to stop and show the summary")
32 34
33def trace_end(): 35def trace_end():
34 print_syscall_totals() 36 print_syscall_totals()
35 37
36def raw_syscalls__sys_enter(event_name, context, common_cpu, 38def raw_syscalls__sys_enter(event_name, context, common_cpu,
37 common_secs, common_nsecs, common_pid, common_comm, 39 common_secs, common_nsecs, common_pid, common_comm,
38 common_callchain, id, args): 40 common_callchain, id, args):
39 if for_comm is not None: 41 if for_comm is not None:
40 if common_comm != for_comm: 42 if common_comm != for_comm:
41 return 43 return
@@ -45,20 +47,19 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
45 syscalls[id] = 1 47 syscalls[id] = 1
46 48
47def syscalls__sys_enter(event_name, context, common_cpu, 49def syscalls__sys_enter(event_name, context, common_cpu,
48 common_secs, common_nsecs, common_pid, common_comm, 50 common_secs, common_nsecs, common_pid, common_comm, id, args):
49 id, args):
50 raw_syscalls__sys_enter(**locals()) 51 raw_syscalls__sys_enter(**locals())
51 52
52def print_syscall_totals(): 53def print_syscall_totals():
53 if for_comm is not None: 54 if for_comm is not None:
54 print "\nsyscall events for %s:\n\n" % (for_comm), 55 print("\nsyscall events for %s:\n" % (for_comm))
55 else: 56 else:
56 print "\nsyscall events:\n\n", 57 print("\nsyscall events:\n")
57 58
58 print "%-40s %10s\n" % ("event", "count"), 59 print("%-40s %10s" % ("event", "count"))
59 print "%-40s %10s\n" % ("----------------------------------------", \ 60 print("%-40s %10s" % ("----------------------------------------",
60 "-----------"), 61 "-----------"))
61 62
62 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ 63 for id, val in sorted(syscalls.items(),
63 reverse = True): 64 key = lambda kv: (kv[1], kv[0]), reverse = True):
64 print "%-40s %10d\n" % (syscall_name(id), val), 65 print("%-40s %10d" % (syscall_name(id), val))