]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blob - tools/perf/scripts/python/export-to-sqlite.py
perf scripts python: export-to-sqlite.py: Add has_calls column to comms table
[mirror_ubuntu-eoan-kernel.git] / tools / perf / scripts / python / export-to-sqlite.py
1 # export-to-sqlite.py: export perf data to a sqlite3 database
2 # Copyright (c) 2017, Intel Corporation.
3 #
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms and conditions of the GNU General Public License,
6 # version 2, as published by the Free Software Foundation.
7 #
8 # This program is distributed in the hope it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 # more details.
12
13 from __future__ import print_function
14
15 import os
16 import sys
17 import struct
18 import datetime
19
20 # To use this script you will need to have installed package python-pyside which
21 # provides LGPL-licensed Python bindings for Qt. You will also need the package
22 # libqt4-sql-sqlite for Qt sqlite3 support.
23 #
24 # Examples of installing pyside:
25 #
26 # ubuntu:
27 #
28 # $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
29 #
30 # Alternately, to use Python3 and/or pyside 2, one of the following:
31 #
32 # $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
33 # $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
34 # $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
35 # fedora:
36 #
37 # $ sudo yum install python-pyside
38 #
39 # Alternately, to use Python3 and/or pyside 2, one of the following:
40 # $ sudo yum install python3-pyside
41 # $ pip install --user PySide2
42 # $ pip3 install --user PySide2
43 #
44 # An example of using this script with Intel PT:
45 #
46 # $ perf record -e intel_pt//u ls
47 # $ perf script -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py pt_example branches calls
48 # 2017-07-31 14:26:07.326913 Creating database...
49 # 2017-07-31 14:26:07.538097 Writing records...
50 # 2017-07-31 14:26:09.889292 Adding indexes
51 # 2017-07-31 14:26:09.958746 Done
52 #
53 # To browse the database, sqlite3 can be used e.g.
54 #
55 # $ sqlite3 pt_example
56 # sqlite> .header on
57 # sqlite> select * from samples_view where id < 10;
58 # sqlite> .mode column
59 # sqlite> select * from samples_view where id < 10;
60 # sqlite> .tables
61 # sqlite> .schema samples_view
62 # sqlite> .quit
63 #
64 # An example of using the database is provided by the script
65 # exported-sql-viewer.py. Refer to that script for details.
66 #
67 # The database structure is practically the same as created by the script
68 # export-to-postgresql.py. Refer to that script for details. A notable
69 # difference is the 'transaction' column of the 'samples' table which is
70 # renamed 'transaction_' in sqlite because 'transaction' is a reserved word.
71
72 pyside_version_1 = True
73 if not "pyside-version-1" in sys.argv:
74 try:
75 from PySide2.QtSql import *
76 pyside_version_1 = False
77 except:
78 pass
79
80 if pyside_version_1:
81 from PySide.QtSql import *
82
83 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
84 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
85
86 # These perf imports are not used at present
87 #from perf_trace_context import *
88 #from Core import *
89
90 perf_db_export_mode = True
91 perf_db_export_calls = False
92 perf_db_export_callchains = False
93
94 def printerr(*args, **keyword_args):
95 print(*args, file=sys.stderr, **keyword_args)
96
97 def printdate(*args, **kw_args):
98 print(datetime.datetime.today(), *args, sep=' ', **kw_args)
99
100 def usage():
101 printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
102 printerr("where: columns 'all' or 'branches'");
103 printerr(" calls 'calls' => create calls and call_paths table");
104 printerr(" callchains 'callchains' => create call_paths table");
105 printerr(" pyside-version-1 'pyside-version-1' => use pyside version 1");
106 raise Exception("Too few or bad arguments")
107
108 if (len(sys.argv) < 2):
109 usage()
110
111 dbname = sys.argv[1]
112
113 if (len(sys.argv) >= 3):
114 columns = sys.argv[2]
115 else:
116 columns = "all"
117
118 if columns not in ("all", "branches"):
119 usage()
120
121 branches = (columns == "branches")
122
123 for i in range(3,len(sys.argv)):
124 if (sys.argv[i] == "calls"):
125 perf_db_export_calls = True
126 elif (sys.argv[i] == "callchains"):
127 perf_db_export_callchains = True
128 elif (sys.argv[i] == "pyside-version-1"):
129 pass
130 else:
131 usage()
132
133 def do_query(q, s):
134 if (q.exec_(s)):
135 return
136 raise Exception("Query failed: " + q.lastError().text())
137
138 def do_query_(q):
139 if (q.exec_()):
140 return
141 raise Exception("Query failed: " + q.lastError().text())
142
143 printdate("Creating database ...")
144
145 db_exists = False
146 try:
147 f = open(dbname)
148 f.close()
149 db_exists = True
150 except:
151 pass
152
153 if db_exists:
154 raise Exception(dbname + " already exists")
155
156 db = QSqlDatabase.addDatabase('QSQLITE')
157 db.setDatabaseName(dbname)
158 db.open()
159
160 query = QSqlQuery(db)
161
162 do_query(query, 'PRAGMA journal_mode = OFF')
163 do_query(query, 'BEGIN TRANSACTION')
164
165 do_query(query, 'CREATE TABLE selected_events ('
166 'id integer NOT NULL PRIMARY KEY,'
167 'name varchar(80))')
168 do_query(query, 'CREATE TABLE machines ('
169 'id integer NOT NULL PRIMARY KEY,'
170 'pid integer,'
171 'root_dir varchar(4096))')
172 do_query(query, 'CREATE TABLE threads ('
173 'id integer NOT NULL PRIMARY KEY,'
174 'machine_id bigint,'
175 'process_id bigint,'
176 'pid integer,'
177 'tid integer)')
178 do_query(query, 'CREATE TABLE comms ('
179 'id integer NOT NULL PRIMARY KEY,'
180 'comm varchar(16),'
181 'c_thread_id bigint,'
182 'c_time bigint,'
183 'exec_flag boolean)')
184 do_query(query, 'CREATE TABLE comm_threads ('
185 'id integer NOT NULL PRIMARY KEY,'
186 'comm_id bigint,'
187 'thread_id bigint)')
188 do_query(query, 'CREATE TABLE dsos ('
189 'id integer NOT NULL PRIMARY KEY,'
190 'machine_id bigint,'
191 'short_name varchar(256),'
192 'long_name varchar(4096),'
193 'build_id varchar(64))')
194 do_query(query, 'CREATE TABLE symbols ('
195 'id integer NOT NULL PRIMARY KEY,'
196 'dso_id bigint,'
197 'sym_start bigint,'
198 'sym_end bigint,'
199 'binding integer,'
200 'name varchar(2048))')
201 do_query(query, 'CREATE TABLE branch_types ('
202 'id integer NOT NULL PRIMARY KEY,'
203 'name varchar(80))')
204
205 if branches:
206 do_query(query, 'CREATE TABLE samples ('
207 'id integer NOT NULL PRIMARY KEY,'
208 'evsel_id bigint,'
209 'machine_id bigint,'
210 'thread_id bigint,'
211 'comm_id bigint,'
212 'dso_id bigint,'
213 'symbol_id bigint,'
214 'sym_offset bigint,'
215 'ip bigint,'
216 'time bigint,'
217 'cpu integer,'
218 'to_dso_id bigint,'
219 'to_symbol_id bigint,'
220 'to_sym_offset bigint,'
221 'to_ip bigint,'
222 'branch_type integer,'
223 'in_tx boolean,'
224 'call_path_id bigint,'
225 'insn_count bigint,'
226 'cyc_count bigint)')
227 else:
228 do_query(query, 'CREATE TABLE samples ('
229 'id integer NOT NULL PRIMARY KEY,'
230 'evsel_id bigint,'
231 'machine_id bigint,'
232 'thread_id bigint,'
233 'comm_id bigint,'
234 'dso_id bigint,'
235 'symbol_id bigint,'
236 'sym_offset bigint,'
237 'ip bigint,'
238 'time bigint,'
239 'cpu integer,'
240 'to_dso_id bigint,'
241 'to_symbol_id bigint,'
242 'to_sym_offset bigint,'
243 'to_ip bigint,'
244 'period bigint,'
245 'weight bigint,'
246 'transaction_ bigint,'
247 'data_src bigint,'
248 'branch_type integer,'
249 'in_tx boolean,'
250 'call_path_id bigint,'
251 'insn_count bigint,'
252 'cyc_count bigint)')
253
254 if perf_db_export_calls or perf_db_export_callchains:
255 do_query(query, 'CREATE TABLE call_paths ('
256 'id integer NOT NULL PRIMARY KEY,'
257 'parent_id bigint,'
258 'symbol_id bigint,'
259 'ip bigint)')
260 if perf_db_export_calls:
261 do_query(query, 'CREATE TABLE calls ('
262 'id integer NOT NULL PRIMARY KEY,'
263 'thread_id bigint,'
264 'comm_id bigint,'
265 'call_path_id bigint,'
266 'call_time bigint,'
267 'return_time bigint,'
268 'branch_count bigint,'
269 'call_id bigint,'
270 'return_id bigint,'
271 'parent_call_path_id bigint,'
272 'flags integer,'
273 'parent_id bigint,'
274 'insn_count bigint,'
275 'cyc_count bigint)')
276
277 do_query(query, 'CREATE TABLE ptwrite ('
278 'id integer NOT NULL PRIMARY KEY,'
279 'payload bigint,'
280 'exact_ip integer)')
281
282 do_query(query, 'CREATE TABLE cbr ('
283 'id integer NOT NULL PRIMARY KEY,'
284 'cbr integer,'
285 'mhz integer,'
286 'percent integer)')
287
288 do_query(query, 'CREATE TABLE mwait ('
289 'id integer NOT NULL PRIMARY KEY,'
290 'hints integer,'
291 'extensions integer)')
292
293 do_query(query, 'CREATE TABLE pwre ('
294 'id integer NOT NULL PRIMARY KEY,'
295 'cstate integer,'
296 'subcstate integer,'
297 'hw integer)')
298
299 do_query(query, 'CREATE TABLE exstop ('
300 'id integer NOT NULL PRIMARY KEY,'
301 'exact_ip integer)')
302
303 do_query(query, 'CREATE TABLE pwrx ('
304 'id integer NOT NULL PRIMARY KEY,'
305 'deepest_cstate integer,'
306 'last_cstate integer,'
307 'wake_reason integer)')
308
309 # printf was added to sqlite in version 3.8.3
310 sqlite_has_printf = False
311 try:
312 do_query(query, 'SELECT printf("") FROM machines')
313 sqlite_has_printf = True
314 except:
315 pass
316
317 def emit_to_hex(x):
318 if sqlite_has_printf:
319 return 'printf("%x", ' + x + ')'
320 else:
321 return x
322
323 do_query(query, 'CREATE VIEW machines_view AS '
324 'SELECT '
325 'id,'
326 'pid,'
327 'root_dir,'
328 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
329 ' FROM machines')
330
331 do_query(query, 'CREATE VIEW dsos_view AS '
332 'SELECT '
333 'id,'
334 'machine_id,'
335 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
336 'short_name,'
337 'long_name,'
338 'build_id'
339 ' FROM dsos')
340
341 do_query(query, 'CREATE VIEW symbols_view AS '
342 'SELECT '
343 'id,'
344 'name,'
345 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
346 'dso_id,'
347 'sym_start,'
348 'sym_end,'
349 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
350 ' FROM symbols')
351
352 do_query(query, 'CREATE VIEW threads_view AS '
353 'SELECT '
354 'id,'
355 'machine_id,'
356 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
357 'process_id,'
358 'pid,'
359 'tid'
360 ' FROM threads')
361
362 do_query(query, 'CREATE VIEW comm_threads_view AS '
363 'SELECT '
364 'comm_id,'
365 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
366 'thread_id,'
367 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
368 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
369 ' FROM comm_threads')
370
371 if perf_db_export_calls or perf_db_export_callchains:
372 do_query(query, 'CREATE VIEW call_paths_view AS '
373 'SELECT '
374 'c.id,'
375 + emit_to_hex('c.ip') + ' AS ip,'
376 'c.symbol_id,'
377 '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
378 '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
379 '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
380 'c.parent_id,'
381 + emit_to_hex('p.ip') + ' AS parent_ip,'
382 'p.symbol_id AS parent_symbol_id,'
383 '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
384 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
385 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
386 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
387 if perf_db_export_calls:
388 do_query(query, 'CREATE VIEW calls_view AS '
389 'SELECT '
390 'calls.id,'
391 'thread_id,'
392 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
393 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
394 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
395 'call_path_id,'
396 + emit_to_hex('ip') + ' AS ip,'
397 'symbol_id,'
398 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
399 'call_time,'
400 'return_time,'
401 'return_time - call_time AS elapsed_time,'
402 'branch_count,'
403 'insn_count,'
404 'cyc_count,'
405 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'
406 'call_id,'
407 'return_id,'
408 '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,'
409 'parent_call_path_id,'
410 'calls.parent_id'
411 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
412
413 do_query(query, 'CREATE VIEW samples_view AS '
414 'SELECT '
415 'id,'
416 'time,'
417 'cpu,'
418 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
419 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
420 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
421 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
422 + emit_to_hex('ip') + ' AS ip_hex,'
423 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
424 'sym_offset,'
425 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
426 + emit_to_hex('to_ip') + ' AS to_ip_hex,'
427 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
428 'to_sym_offset,'
429 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
430 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
431 'in_tx,'
432 'insn_count,'
433 'cyc_count,'
434 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC'
435 ' FROM samples')
436
437 do_query(query, 'CREATE VIEW ptwrite_view AS '
438 'SELECT '
439 'ptwrite.id,'
440 'time,'
441 'cpu,'
442 + emit_to_hex('payload') + ' AS payload_hex,'
443 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
444 ' FROM ptwrite'
445 ' INNER JOIN samples ON samples.id = ptwrite.id')
446
447 do_query(query, 'CREATE VIEW cbr_view AS '
448 'SELECT '
449 'cbr.id,'
450 'time,'
451 'cpu,'
452 'cbr,'
453 'mhz,'
454 'percent'
455 ' FROM cbr'
456 ' INNER JOIN samples ON samples.id = cbr.id')
457
458 do_query(query, 'CREATE VIEW mwait_view AS '
459 'SELECT '
460 'mwait.id,'
461 'time,'
462 'cpu,'
463 + emit_to_hex('hints') + ' AS hints_hex,'
464 + emit_to_hex('extensions') + ' AS extensions_hex'
465 ' FROM mwait'
466 ' INNER JOIN samples ON samples.id = mwait.id')
467
468 do_query(query, 'CREATE VIEW pwre_view AS '
469 'SELECT '
470 'pwre.id,'
471 'time,'
472 'cpu,'
473 'cstate,'
474 'subcstate,'
475 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw'
476 ' FROM pwre'
477 ' INNER JOIN samples ON samples.id = pwre.id')
478
479 do_query(query, 'CREATE VIEW exstop_view AS '
480 'SELECT '
481 'exstop.id,'
482 'time,'
483 'cpu,'
484 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
485 ' FROM exstop'
486 ' INNER JOIN samples ON samples.id = exstop.id')
487
488 do_query(query, 'CREATE VIEW pwrx_view AS '
489 'SELECT '
490 'pwrx.id,'
491 'time,'
492 'cpu,'
493 'deepest_cstate,'
494 'last_cstate,'
495 'CASE WHEN wake_reason=1 THEN \'Interrupt\''
496 ' WHEN wake_reason=2 THEN \'Timer Deadline\''
497 ' WHEN wake_reason=4 THEN \'Monitored Address\''
498 ' WHEN wake_reason=8 THEN \'HW\''
499 ' ELSE wake_reason '
500 'END AS wake_reason'
501 ' FROM pwrx'
502 ' INNER JOIN samples ON samples.id = pwrx.id')
503
504 do_query(query, 'CREATE VIEW power_events_view AS '
505 'SELECT '
506 'samples.id,'
507 'time,'
508 'cpu,'
509 'selected_events.name AS event,'
510 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,'
511 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,'
512 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,'
513 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,'
514 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,'
515 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,'
516 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,'
517 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,'
518 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,'
519 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,'
520 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,'
521 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT '
522 'CASE WHEN wake_reason=1 THEN \'Interrupt\''
523 ' WHEN wake_reason=2 THEN \'Timer Deadline\''
524 ' WHEN wake_reason=4 THEN \'Monitored Address\''
525 ' WHEN wake_reason=8 THEN \'HW\''
526 ' ELSE wake_reason '
527 'END'
528 ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason'
529 ' FROM samples'
530 ' INNER JOIN selected_events ON selected_events.id = evsel_id'
531 ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')')
532
533 do_query(query, 'END TRANSACTION')
534
535 evsel_query = QSqlQuery(db)
536 evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")
537 machine_query = QSqlQuery(db)
538 machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")
539 thread_query = QSqlQuery(db)
540 thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")
541 comm_query = QSqlQuery(db)
542 comm_query.prepare("INSERT INTO comms VALUES (?, ?, ?, ?, ?)")
543 comm_thread_query = QSqlQuery(db)
544 comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")
545 dso_query = QSqlQuery(db)
546 dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")
547 symbol_query = QSqlQuery(db)
548 symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")
549 branch_type_query = QSqlQuery(db)
550 branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")
551 sample_query = QSqlQuery(db)
552 if branches:
553 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
554 else:
555 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
556 if perf_db_export_calls or perf_db_export_callchains:
557 call_path_query = QSqlQuery(db)
558 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
559 if perf_db_export_calls:
560 call_query = QSqlQuery(db)
561 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
562 ptwrite_query = QSqlQuery(db)
563 ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)")
564 cbr_query = QSqlQuery(db)
565 cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)")
566 mwait_query = QSqlQuery(db)
567 mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)")
568 pwre_query = QSqlQuery(db)
569 pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)")
570 exstop_query = QSqlQuery(db)
571 exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)")
572 pwrx_query = QSqlQuery(db)
573 pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")
574
575 def trace_begin():
576 printdate("Writing records...")
577 do_query(query, 'BEGIN TRANSACTION')
578 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
579 evsel_table(0, "unknown")
580 machine_table(0, 0, "unknown")
581 thread_table(0, 0, 0, -1, -1)
582 comm_table(0, "unknown", 0, 0, 0)
583 dso_table(0, 0, "unknown", "unknown", "")
584 symbol_table(0, 0, 0, 0, 0, "unknown")
585 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
586 if perf_db_export_calls or perf_db_export_callchains:
587 call_path_table(0, 0, 0, 0)
588 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
589
590 unhandled_count = 0
591
592 def is_table_empty(table_name):
593 do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');
594 if query.next():
595 return False
596 return True
597
598 def drop(table_name):
599 do_query(query, 'DROP VIEW ' + table_name + '_view');
600 do_query(query, 'DROP TABLE ' + table_name);
601
602 def trace_end():
603 do_query(query, 'END TRANSACTION')
604
605 printdate("Adding indexes")
606 if perf_db_export_calls:
607 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
608 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
609 do_query(query, 'ALTER TABLE comms ADD has_calls boolean')
610 do_query(query, 'UPDATE comms SET has_calls = 1 WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)')
611
612 printdate("Dropping unused tables")
613 if is_table_empty("ptwrite"):
614 drop("ptwrite")
615 if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):
616 do_query(query, 'DROP VIEW power_events_view');
617 drop("mwait")
618 drop("pwre")
619 drop("exstop")
620 drop("pwrx")
621 if is_table_empty("cbr"):
622 drop("cbr")
623
624 if (unhandled_count):
625 printdate("Warning: ", unhandled_count, " unhandled events")
626 printdate("Done")
627
628 def trace_unhandled(event_name, context, event_fields_dict):
629 global unhandled_count
630 unhandled_count += 1
631
632 def sched__sched_switch(*x):
633 pass
634
635 def bind_exec(q, n, x):
636 for xx in x[0:n]:
637 q.addBindValue(str(xx))
638 do_query_(q)
639
640 def evsel_table(*x):
641 bind_exec(evsel_query, 2, x)
642
643 def machine_table(*x):
644 bind_exec(machine_query, 3, x)
645
646 def thread_table(*x):
647 bind_exec(thread_query, 5, x)
648
649 def comm_table(*x):
650 bind_exec(comm_query, 5, x)
651
652 def comm_thread_table(*x):
653 bind_exec(comm_thread_query, 3, x)
654
655 def dso_table(*x):
656 bind_exec(dso_query, 5, x)
657
658 def symbol_table(*x):
659 bind_exec(symbol_query, 6, x)
660
661 def branch_type_table(*x):
662 bind_exec(branch_type_query, 2, x)
663
664 def sample_table(*x):
665 if branches:
666 for xx in x[0:15]:
667 sample_query.addBindValue(str(xx))
668 for xx in x[19:24]:
669 sample_query.addBindValue(str(xx))
670 do_query_(sample_query)
671 else:
672 bind_exec(sample_query, 24, x)
673
674 def call_path_table(*x):
675 bind_exec(call_path_query, 4, x)
676
677 def call_return_table(*x):
678 bind_exec(call_query, 14, x)
679
680 def ptwrite(id, raw_buf):
681 data = struct.unpack_from("<IQ", raw_buf)
682 flags = data[0]
683 payload = data[1]
684 exact_ip = flags & 1
685 ptwrite_query.addBindValue(str(id))
686 ptwrite_query.addBindValue(str(payload))
687 ptwrite_query.addBindValue(str(exact_ip))
688 do_query_(ptwrite_query)
689
690 def cbr(id, raw_buf):
691 data = struct.unpack_from("<BBBBII", raw_buf)
692 cbr = data[0]
693 MHz = (data[4] + 500) / 1000
694 percent = ((cbr * 1000 / data[2]) + 5) / 10
695 cbr_query.addBindValue(str(id))
696 cbr_query.addBindValue(str(cbr))
697 cbr_query.addBindValue(str(MHz))
698 cbr_query.addBindValue(str(percent))
699 do_query_(cbr_query)
700
701 def mwait(id, raw_buf):
702 data = struct.unpack_from("<IQ", raw_buf)
703 payload = data[1]
704 hints = payload & 0xff
705 extensions = (payload >> 32) & 0x3
706 mwait_query.addBindValue(str(id))
707 mwait_query.addBindValue(str(hints))
708 mwait_query.addBindValue(str(extensions))
709 do_query_(mwait_query)
710
711 def pwre(id, raw_buf):
712 data = struct.unpack_from("<IQ", raw_buf)
713 payload = data[1]
714 hw = (payload >> 7) & 1
715 cstate = (payload >> 12) & 0xf
716 subcstate = (payload >> 8) & 0xf
717 pwre_query.addBindValue(str(id))
718 pwre_query.addBindValue(str(cstate))
719 pwre_query.addBindValue(str(subcstate))
720 pwre_query.addBindValue(str(hw))
721 do_query_(pwre_query)
722
723 def exstop(id, raw_buf):
724 data = struct.unpack_from("<I", raw_buf)
725 flags = data[0]
726 exact_ip = flags & 1
727 exstop_query.addBindValue(str(id))
728 exstop_query.addBindValue(str(exact_ip))
729 do_query_(exstop_query)
730
731 def pwrx(id, raw_buf):
732 data = struct.unpack_from("<IQ", raw_buf)
733 payload = data[1]
734 deepest_cstate = payload & 0xf
735 last_cstate = (payload >> 4) & 0xf
736 wake_reason = (payload >> 8) & 0xf
737 pwrx_query.addBindValue(str(id))
738 pwrx_query.addBindValue(str(deepest_cstate))
739 pwrx_query.addBindValue(str(last_cstate))
740 pwrx_query.addBindValue(str(wake_reason))
741 do_query_(pwrx_query)
742
743 def synth_data(id, config, raw_buf, *x):
744 if config == 0:
745 ptwrite(id, raw_buf)
746 elif config == 1:
747 mwait(id, raw_buf)
748 elif config == 2:
749 pwre(id, raw_buf)
750 elif config == 3:
751 exstop(id, raw_buf)
752 elif config == 4:
753 pwrx(id, raw_buf)
754 elif config == 5:
755 cbr(id, raw_buf)