800 lines · python
1# export-to-sqlite.py: export perf data to a sqlite3 database2# Copyright (c) 2017, Intel Corporation.3#4# This program is free software; you can redistribute it and/or modify it5# 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 WITHOUT9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11# more details.12 13from __future__ import print_function14 15import os16import sys17import struct18import datetime19 20# To use this script you will need to have installed package python-pyside which21# provides LGPL-licensed Python bindings for Qt. You will also need the package22# 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-psql29#30# Alternately, to use Python3 and/or pyside 2, one of the following:31#32# $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql33# $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql34# $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql35# fedora:36#37# $ sudo yum install python-pyside38#39# Alternately, to use Python3 and/or pyside 2, one of the following:40# $ sudo yum install python3-pyside41# $ pip install --user PySide242# $ pip3 install --user PySide243#44# An example of using this script with Intel PT:45#46# $ perf record -e intel_pt//u ls47# $ perf script -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py pt_example branches calls48# 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 indexes51# 2017-07-31 14:26:09.958746 Done52#53# To browse the database, sqlite3 can be used e.g.54#55# $ sqlite3 pt_example56# sqlite> .header on57# sqlite> select * from samples_view where id < 10;58# sqlite> .mode column59# sqlite> select * from samples_view where id < 10;60# sqlite> .tables61# sqlite> .schema samples_view62# sqlite> .quit63#64# An example of using the database is provided by the script65# exported-sql-viewer.py. Refer to that script for details.66#67# The database structure is practically the same as created by the script68# export-to-postgresql.py. Refer to that script for details. A notable69# difference is the 'transaction' column of the 'samples' table which is70# renamed 'transaction_' in sqlite because 'transaction' is a reserved word.71 72pyside_version_1 = True73if not "pyside-version-1" in sys.argv:74 try:75 from PySide2.QtSql import *76 pyside_version_1 = False77 except:78 pass79 80if pyside_version_1:81 from PySide.QtSql import *82 83sys.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 present87#from perf_trace_context import *88#from Core import *89 90perf_db_export_mode = True91perf_db_export_calls = False92perf_db_export_callchains = False93 94def printerr(*args, **keyword_args):95 print(*args, file=sys.stderr, **keyword_args)96 97def printdate(*args, **kw_args):98 print(datetime.datetime.today(), *args, sep=' ', **kw_args)99 100def 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 108if (len(sys.argv) < 2):109 usage()110 111dbname = sys.argv[1]112 113if (len(sys.argv) >= 3):114 columns = sys.argv[2]115else:116 columns = "all"117 118if columns not in ("all", "branches"):119 usage()120 121branches = (columns == "branches")122 123for i in range(3,len(sys.argv)):124 if (sys.argv[i] == "calls"):125 perf_db_export_calls = True126 elif (sys.argv[i] == "callchains"):127 perf_db_export_callchains = True128 elif (sys.argv[i] == "pyside-version-1"):129 pass130 else:131 usage()132 133def do_query(q, s):134 if (q.exec_(s)):135 return136 raise Exception("Query failed: " + q.lastError().text())137 138def do_query_(q):139 if (q.exec_()):140 return141 raise Exception("Query failed: " + q.lastError().text())142 143printdate("Creating database ...")144 145db_exists = False146try:147 f = open(dbname)148 f.close()149 db_exists = True150except:151 pass152 153if db_exists:154 raise Exception(dbname + " already exists")155 156db = QSqlDatabase.addDatabase('QSQLITE')157db.setDatabaseName(dbname)158db.open()159 160query = QSqlQuery(db)161 162do_query(query, 'PRAGMA journal_mode = OFF')163do_query(query, 'BEGIN TRANSACTION')164 165do_query(query, 'CREATE TABLE selected_events ('166 'id integer NOT NULL PRIMARY KEY,'167 'name varchar(80))')168do_query(query, 'CREATE TABLE machines ('169 'id integer NOT NULL PRIMARY KEY,'170 'pid integer,'171 'root_dir varchar(4096))')172do_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)')178do_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)')184do_query(query, 'CREATE TABLE comm_threads ('185 'id integer NOT NULL PRIMARY KEY,'186 'comm_id bigint,'187 'thread_id bigint)')188do_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))')194do_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))')201do_query(query, 'CREATE TABLE branch_types ('202 'id integer NOT NULL PRIMARY KEY,'203 'name varchar(80))')204 205if 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 'flags integer)')228else:229 do_query(query, 'CREATE TABLE samples ('230 'id integer NOT NULL PRIMARY KEY,'231 'evsel_id bigint,'232 'machine_id bigint,'233 'thread_id bigint,'234 'comm_id bigint,'235 'dso_id bigint,'236 'symbol_id bigint,'237 'sym_offset bigint,'238 'ip bigint,'239 'time bigint,'240 'cpu integer,'241 'to_dso_id bigint,'242 'to_symbol_id bigint,'243 'to_sym_offset bigint,'244 'to_ip bigint,'245 'period bigint,'246 'weight bigint,'247 'transaction_ bigint,'248 'data_src bigint,'249 'branch_type integer,'250 'in_tx boolean,'251 'call_path_id bigint,'252 'insn_count bigint,'253 'cyc_count bigint,'254 'flags integer)')255 256if perf_db_export_calls or perf_db_export_callchains:257 do_query(query, 'CREATE TABLE call_paths ('258 'id integer NOT NULL PRIMARY KEY,'259 'parent_id bigint,'260 'symbol_id bigint,'261 'ip bigint)')262if perf_db_export_calls:263 do_query(query, 'CREATE TABLE calls ('264 'id integer NOT NULL PRIMARY KEY,'265 'thread_id bigint,'266 'comm_id bigint,'267 'call_path_id bigint,'268 'call_time bigint,'269 'return_time bigint,'270 'branch_count bigint,'271 'call_id bigint,'272 'return_id bigint,'273 'parent_call_path_id bigint,'274 'flags integer,'275 'parent_id bigint,'276 'insn_count bigint,'277 'cyc_count bigint)')278 279do_query(query, 'CREATE TABLE ptwrite ('280 'id integer NOT NULL PRIMARY KEY,'281 'payload bigint,'282 'exact_ip integer)')283 284do_query(query, 'CREATE TABLE cbr ('285 'id integer NOT NULL PRIMARY KEY,'286 'cbr integer,'287 'mhz integer,'288 'percent integer)')289 290do_query(query, 'CREATE TABLE mwait ('291 'id integer NOT NULL PRIMARY KEY,'292 'hints integer,'293 'extensions integer)')294 295do_query(query, 'CREATE TABLE pwre ('296 'id integer NOT NULL PRIMARY KEY,'297 'cstate integer,'298 'subcstate integer,'299 'hw integer)')300 301do_query(query, 'CREATE TABLE exstop ('302 'id integer NOT NULL PRIMARY KEY,'303 'exact_ip integer)')304 305do_query(query, 'CREATE TABLE pwrx ('306 'id integer NOT NULL PRIMARY KEY,'307 'deepest_cstate integer,'308 'last_cstate integer,'309 'wake_reason integer)')310 311do_query(query, 'CREATE TABLE context_switches ('312 'id integer NOT NULL PRIMARY KEY,'313 'machine_id bigint,'314 'time bigint,'315 'cpu integer,'316 'thread_out_id bigint,'317 'comm_out_id bigint,'318 'thread_in_id bigint,'319 'comm_in_id bigint,'320 'flags integer)')321 322# printf was added to sqlite in version 3.8.3323sqlite_has_printf = False324try:325 do_query(query, 'SELECT printf("") FROM machines')326 sqlite_has_printf = True327except:328 pass329 330def emit_to_hex(x):331 if sqlite_has_printf:332 return 'printf("%x", ' + x + ')'333 else:334 return x335 336do_query(query, 'CREATE VIEW machines_view AS '337 'SELECT '338 'id,'339 'pid,'340 'root_dir,'341 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'342 ' FROM machines')343 344do_query(query, 'CREATE VIEW dsos_view AS '345 'SELECT '346 'id,'347 'machine_id,'348 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'349 'short_name,'350 'long_name,'351 'build_id'352 ' FROM dsos')353 354do_query(query, 'CREATE VIEW symbols_view AS '355 'SELECT '356 'id,'357 'name,'358 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'359 'dso_id,'360 'sym_start,'361 'sym_end,'362 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'363 ' FROM symbols')364 365do_query(query, 'CREATE VIEW threads_view AS '366 'SELECT '367 'id,'368 'machine_id,'369 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'370 'process_id,'371 'pid,'372 'tid'373 ' FROM threads')374 375do_query(query, 'CREATE VIEW comm_threads_view AS '376 'SELECT '377 'comm_id,'378 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'379 'thread_id,'380 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'381 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'382 ' FROM comm_threads')383 384if perf_db_export_calls or perf_db_export_callchains:385 do_query(query, 'CREATE VIEW call_paths_view AS '386 'SELECT '387 'c.id,'388 + emit_to_hex('c.ip') + ' AS ip,'389 'c.symbol_id,'390 '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'391 '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'392 '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'393 'c.parent_id,'394 + emit_to_hex('p.ip') + ' AS parent_ip,'395 'p.symbol_id AS parent_symbol_id,'396 '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'397 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'398 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'399 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')400if perf_db_export_calls:401 do_query(query, 'CREATE VIEW calls_view AS '402 'SELECT '403 'calls.id,'404 'thread_id,'405 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'406 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'407 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'408 'call_path_id,'409 + emit_to_hex('ip') + ' AS ip,'410 'symbol_id,'411 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'412 'call_time,'413 'return_time,'414 'return_time - call_time AS elapsed_time,'415 'branch_count,'416 'insn_count,'417 'cyc_count,'418 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'419 'call_id,'420 'return_id,'421 '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,'422 'parent_call_path_id,'423 'calls.parent_id'424 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')425 426do_query(query, 'CREATE VIEW samples_view AS '427 'SELECT '428 'id,'429 'time,'430 'cpu,'431 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'432 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'433 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'434 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'435 + emit_to_hex('ip') + ' AS ip_hex,'436 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'437 'sym_offset,'438 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'439 + emit_to_hex('to_ip') + ' AS to_ip_hex,'440 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'441 'to_sym_offset,'442 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'443 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'444 'in_tx,'445 'insn_count,'446 'cyc_count,'447 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'448 'flags'449 ' FROM samples')450 451do_query(query, 'CREATE VIEW ptwrite_view AS '452 'SELECT '453 'ptwrite.id,'454 'time,'455 'cpu,'456 + emit_to_hex('payload') + ' AS payload_hex,'457 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'458 ' FROM ptwrite'459 ' INNER JOIN samples ON samples.id = ptwrite.id')460 461do_query(query, 'CREATE VIEW cbr_view AS '462 'SELECT '463 'cbr.id,'464 'time,'465 'cpu,'466 'cbr,'467 'mhz,'468 'percent'469 ' FROM cbr'470 ' INNER JOIN samples ON samples.id = cbr.id')471 472do_query(query, 'CREATE VIEW mwait_view AS '473 'SELECT '474 'mwait.id,'475 'time,'476 'cpu,'477 + emit_to_hex('hints') + ' AS hints_hex,'478 + emit_to_hex('extensions') + ' AS extensions_hex'479 ' FROM mwait'480 ' INNER JOIN samples ON samples.id = mwait.id')481 482do_query(query, 'CREATE VIEW pwre_view AS '483 'SELECT '484 'pwre.id,'485 'time,'486 'cpu,'487 'cstate,'488 'subcstate,'489 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw'490 ' FROM pwre'491 ' INNER JOIN samples ON samples.id = pwre.id')492 493do_query(query, 'CREATE VIEW exstop_view AS '494 'SELECT '495 'exstop.id,'496 'time,'497 'cpu,'498 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'499 ' FROM exstop'500 ' INNER JOIN samples ON samples.id = exstop.id')501 502do_query(query, 'CREATE VIEW pwrx_view AS '503 'SELECT '504 'pwrx.id,'505 'time,'506 'cpu,'507 'deepest_cstate,'508 'last_cstate,'509 'CASE WHEN wake_reason=1 THEN \'Interrupt\''510 ' WHEN wake_reason=2 THEN \'Timer Deadline\''511 ' WHEN wake_reason=4 THEN \'Monitored Address\''512 ' WHEN wake_reason=8 THEN \'HW\''513 ' ELSE wake_reason '514 'END AS wake_reason'515 ' FROM pwrx'516 ' INNER JOIN samples ON samples.id = pwrx.id')517 518do_query(query, 'CREATE VIEW power_events_view AS '519 'SELECT '520 'samples.id,'521 'time,'522 'cpu,'523 'selected_events.name AS event,'524 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,'525 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,'526 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,'527 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,'528 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,'529 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,'530 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,'531 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,'532 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,'533 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,'534 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,'535 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT '536 'CASE WHEN wake_reason=1 THEN \'Interrupt\''537 ' WHEN wake_reason=2 THEN \'Timer Deadline\''538 ' WHEN wake_reason=4 THEN \'Monitored Address\''539 ' WHEN wake_reason=8 THEN \'HW\''540 ' ELSE wake_reason '541 'END'542 ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason'543 ' FROM samples'544 ' INNER JOIN selected_events ON selected_events.id = evsel_id'545 ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')')546 547do_query(query, 'CREATE VIEW context_switches_view AS '548 'SELECT '549 'context_switches.id,'550 'context_switches.machine_id,'551 'context_switches.time,'552 'context_switches.cpu,'553 'th_out.pid AS pid_out,'554 'th_out.tid AS tid_out,'555 'comm_out.comm AS comm_out,'556 'th_in.pid AS pid_in,'557 'th_in.tid AS tid_in,'558 'comm_in.comm AS comm_in,'559 'CASE WHEN context_switches.flags = 0 THEN \'in\''560 ' WHEN context_switches.flags = 1 THEN \'out\''561 ' WHEN context_switches.flags = 3 THEN \'out preempt\''562 ' ELSE context_switches.flags '563 'END AS flags'564 ' FROM context_switches'565 ' INNER JOIN threads AS th_out ON th_out.id = context_switches.thread_out_id'566 ' INNER JOIN threads AS th_in ON th_in.id = context_switches.thread_in_id'567 ' INNER JOIN comms AS comm_out ON comm_out.id = context_switches.comm_out_id'568 ' INNER JOIN comms AS comm_in ON comm_in.id = context_switches.comm_in_id')569 570do_query(query, 'END TRANSACTION')571 572evsel_query = QSqlQuery(db)573evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")574machine_query = QSqlQuery(db)575machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")576thread_query = QSqlQuery(db)577thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")578comm_query = QSqlQuery(db)579comm_query.prepare("INSERT INTO comms VALUES (?, ?, ?, ?, ?)")580comm_thread_query = QSqlQuery(db)581comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")582dso_query = QSqlQuery(db)583dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")584symbol_query = QSqlQuery(db)585symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")586branch_type_query = QSqlQuery(db)587branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")588sample_query = QSqlQuery(db)589if branches:590 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")591else:592 sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")593if perf_db_export_calls or perf_db_export_callchains:594 call_path_query = QSqlQuery(db)595 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")596if perf_db_export_calls:597 call_query = QSqlQuery(db)598 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")599ptwrite_query = QSqlQuery(db)600ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)")601cbr_query = QSqlQuery(db)602cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)")603mwait_query = QSqlQuery(db)604mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)")605pwre_query = QSqlQuery(db)606pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)")607exstop_query = QSqlQuery(db)608exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)")609pwrx_query = QSqlQuery(db)610pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")611context_switch_query = QSqlQuery(db)612context_switch_query.prepare("INSERT INTO context_switches VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")613 614def trace_begin():615 printdate("Writing records...")616 do_query(query, 'BEGIN TRANSACTION')617 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs618 evsel_table(0, "unknown")619 machine_table(0, 0, "unknown")620 thread_table(0, 0, 0, -1, -1)621 comm_table(0, "unknown", 0, 0, 0)622 dso_table(0, 0, "unknown", "unknown", "")623 symbol_table(0, 0, 0, 0, 0, "unknown")624 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, 0)625 if perf_db_export_calls or perf_db_export_callchains:626 call_path_table(0, 0, 0, 0)627 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)628 629unhandled_count = 0630 631def is_table_empty(table_name):632 do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');633 if query.next():634 return False635 return True636 637def drop(table_name):638 do_query(query, 'DROP VIEW ' + table_name + '_view');639 do_query(query, 'DROP TABLE ' + table_name);640 641def trace_end():642 do_query(query, 'END TRANSACTION')643 644 printdate("Adding indexes")645 if perf_db_export_calls:646 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')647 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')648 do_query(query, 'ALTER TABLE comms ADD has_calls boolean')649 do_query(query, 'UPDATE comms SET has_calls = 1 WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)')650 651 printdate("Dropping unused tables")652 if is_table_empty("ptwrite"):653 drop("ptwrite")654 if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):655 do_query(query, 'DROP VIEW power_events_view');656 drop("mwait")657 drop("pwre")658 drop("exstop")659 drop("pwrx")660 if is_table_empty("cbr"):661 drop("cbr")662 if is_table_empty("context_switches"):663 drop("context_switches")664 665 if (unhandled_count):666 printdate("Warning: ", unhandled_count, " unhandled events")667 printdate("Done")668 669def trace_unhandled(event_name, context, event_fields_dict):670 global unhandled_count671 unhandled_count += 1672 673def sched__sched_switch(*x):674 pass675 676def bind_exec(q, n, x):677 for xx in x[0:n]:678 q.addBindValue(str(xx))679 do_query_(q)680 681def evsel_table(*x):682 bind_exec(evsel_query, 2, x)683 684def machine_table(*x):685 bind_exec(machine_query, 3, x)686 687def thread_table(*x):688 bind_exec(thread_query, 5, x)689 690def comm_table(*x):691 bind_exec(comm_query, 5, x)692 693def comm_thread_table(*x):694 bind_exec(comm_thread_query, 3, x)695 696def dso_table(*x):697 bind_exec(dso_query, 5, x)698 699def symbol_table(*x):700 bind_exec(symbol_query, 6, x)701 702def branch_type_table(*x):703 bind_exec(branch_type_query, 2, x)704 705def sample_table(*x):706 if branches:707 for xx in x[0:15]:708 sample_query.addBindValue(str(xx))709 for xx in x[19:25]:710 sample_query.addBindValue(str(xx))711 do_query_(sample_query)712 else:713 bind_exec(sample_query, 25, x)714 715def call_path_table(*x):716 bind_exec(call_path_query, 4, x)717 718def call_return_table(*x):719 bind_exec(call_query, 14, x)720 721def ptwrite(id, raw_buf):722 data = struct.unpack_from("<IQ", raw_buf)723 flags = data[0]724 payload = data[1]725 exact_ip = flags & 1726 ptwrite_query.addBindValue(str(id))727 ptwrite_query.addBindValue(str(payload))728 ptwrite_query.addBindValue(str(exact_ip))729 do_query_(ptwrite_query)730 731def cbr(id, raw_buf):732 data = struct.unpack_from("<BBBBII", raw_buf)733 cbr = data[0]734 MHz = (data[4] + 500) / 1000735 percent = ((cbr * 1000 / data[2]) + 5) / 10736 cbr_query.addBindValue(str(id))737 cbr_query.addBindValue(str(cbr))738 cbr_query.addBindValue(str(MHz))739 cbr_query.addBindValue(str(percent))740 do_query_(cbr_query)741 742def mwait(id, raw_buf):743 data = struct.unpack_from("<IQ", raw_buf)744 payload = data[1]745 hints = payload & 0xff746 extensions = (payload >> 32) & 0x3747 mwait_query.addBindValue(str(id))748 mwait_query.addBindValue(str(hints))749 mwait_query.addBindValue(str(extensions))750 do_query_(mwait_query)751 752def pwre(id, raw_buf):753 data = struct.unpack_from("<IQ", raw_buf)754 payload = data[1]755 hw = (payload >> 7) & 1756 cstate = (payload >> 12) & 0xf757 subcstate = (payload >> 8) & 0xf758 pwre_query.addBindValue(str(id))759 pwre_query.addBindValue(str(cstate))760 pwre_query.addBindValue(str(subcstate))761 pwre_query.addBindValue(str(hw))762 do_query_(pwre_query)763 764def exstop(id, raw_buf):765 data = struct.unpack_from("<I", raw_buf)766 flags = data[0]767 exact_ip = flags & 1768 exstop_query.addBindValue(str(id))769 exstop_query.addBindValue(str(exact_ip))770 do_query_(exstop_query)771 772def pwrx(id, raw_buf):773 data = struct.unpack_from("<IQ", raw_buf)774 payload = data[1]775 deepest_cstate = payload & 0xf776 last_cstate = (payload >> 4) & 0xf777 wake_reason = (payload >> 8) & 0xf778 pwrx_query.addBindValue(str(id))779 pwrx_query.addBindValue(str(deepest_cstate))780 pwrx_query.addBindValue(str(last_cstate))781 pwrx_query.addBindValue(str(wake_reason))782 do_query_(pwrx_query)783 784def synth_data(id, config, raw_buf, *x):785 if config == 0:786 ptwrite(id, raw_buf)787 elif config == 1:788 mwait(id, raw_buf)789 elif config == 2:790 pwre(id, raw_buf)791 elif config == 3:792 exstop(id, raw_buf)793 elif config == 4:794 pwrx(id, raw_buf)795 elif config == 5:796 cbr(id, raw_buf)797 798def context_switch_table(*x):799 bind_exec(context_switch_query, 9, x)800