diff options
| author | 2019-07-09 11:15:52 -0700 | |
|---|---|---|
| committer | 2019-07-09 11:15:52 -0700 | |
| commit | 608745f12462e2d8d94d5cc5dc94bf0960a881e3 (patch) | |
| tree | e938bc957d235018d1cf4b018b09aaffae8a5f34 /tools/perf/scripts/python/export-to-sqlite.py | |
| parent | Merge tag 'for-5.3/libata-20190708' of git://git.kernel.dk/linux-block (diff) | |
| parent | Merge tag 'perf-urgent-for-mingo-5.3-20190708-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (diff) | |
| download | linux-rng-608745f12462e2d8d94d5cc5dc94bf0960a881e3.tar.xz linux-rng-608745f12462e2d8d94d5cc5dc94bf0960a881e3.zip | |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
 "The main changes in this cycle on the kernel side were:
   - CPU PMU and uncore driver updates to Intel Snow Ridge, IceLake,
     KabyLake, AmberLake and WhiskeyLake CPUs.
   - Rework the MSR probing infrastructure to make it more robust, make
     it work better on virtualized systems and to better expose it on
     sysfs.
   - Rework PMU attributes group support based on the feedback from
     Greg. The core sysfs patch that adds sysfs_update_groups() was
     acked by Greg.
  There's a lot of perf tooling changes as well, all around the place:
   - vendor updates to Intel, cs-etm (ARM), ARM64, s390,
   - various enhancements to Intel PT tooling support:
      - Improve CBR (Core to Bus Ratio) packets support.
      - Export power and ptwrite events to sqlite and postgresql.
      - Add support for decoding PEBS via PT packets.
      - Add support for samples to contain IPC ratio, collecting cycles
        information from CYC packets, showing the IPC info periodically
      - Allow using time ranges
   - lots of updates to perf pmu, perf stat, perf trace, eBPF support,
     perf record, perf diff, etc. - please see the shortlog and Git log
     for details"
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (252 commits)
  tools arch x86: Sync asm/cpufeatures.h with the with the kernel
  tools build: Check if gettid() is available before providing helper
  perf jvmti: Address gcc string overflow warning for strncpy()
  perf python: Remove -fstack-protector-strong if clang doesn't have it
  perf annotate TUI browser: Do not use member from variable within its own initialization
  perf tests: Fix record+probe_libc_inet_pton.sh for powerpc64
  perf evsel: Do not rely on errno values for precise_ip fallback
  perf thread: Allow references to thread objects after machine__exit()
  perf header: Assign proper ff->ph in perf_event__synthesize_features()
  tools arch kvm: Sync kvm headers with the kernel sources
  perf script: Allow specifying the files to process guest samples
  perf tools metric: Don't include duration_time in group
  perf list: Avoid extra : for --raw metrics
  perf vendor events intel: Metric fixes for SKX/CLX
  perf tools: Fix typos / broken sentences
  perf jevents: Add support for Hisi hip08 L3C PMU aliasing
  perf jevents: Add support for Hisi hip08 HHA PMU aliasing
  perf jevents: Add support for Hisi hip08 DDRC PMU aliasing
  perf pmu: Support more complex PMU event aliasing
  perf diff: Documentation -c cycles option
  ...
Diffstat (limited to '')
| -rw-r--r-- | tools/perf/scripts/python/export-to-sqlite.py | 319 | 
1 files changed, 301 insertions, 18 deletions
| diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index bf271fbc3a88..3222a83f4184 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py @@ -21,6 +21,26 @@ import datetime  # provides LGPL-licensed Python bindings for Qt.  You will also need the package  # libqt4-sql-sqlite for Qt sqlite3 support.  # +# Examples of installing pyside: +# +# ubuntu: +# +#	$ sudo apt-get install python-pyside.qtsql libqt4-sql-psql +# +#	Alternately, to use Python3 and/or pyside 2, one of the following: +# +#		$ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql +#		$ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql +#		$ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql +# fedora: +# +#	$ sudo yum install python-pyside +# +#	Alternately, to use Python3 and/or pyside 2, one of the following: +#		$ sudo yum install python3-pyside +#		$ pip install --user PySide2 +#		$ pip3 install --user PySide2 +#  # An example of using this script with Intel PT:  #  #	$ perf record -e intel_pt//u ls @@ -49,7 +69,16 @@ import datetime  # difference is  the 'transaction' column of the 'samples' table which is  # renamed 'transaction_' in sqlite because 'transaction' is a reserved word. -from PySide.QtSql import * +pyside_version_1 = True +if not "pyside-version-1" in sys.argv: +	try: +		from PySide2.QtSql import * +		pyside_version_1 = False +	except: +		pass + +if pyside_version_1: +	from PySide.QtSql import *  sys.path.append(os.environ['PERF_EXEC_PATH'] + \  	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace') @@ -69,11 +98,12 @@ def printdate(*args, **kw_args):          print(datetime.datetime.today(), *args, sep=' ', **kw_args)  def usage(): -	printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]"); -	printerr("where:	columns		'all' or 'branches'"); -	printerr("		calls		'calls' => create calls and call_paths table"); -	printerr("		callchains	'callchains' => create call_paths table"); -	raise Exception("Too few arguments") +	printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]"); +	printerr("where:  columns            'all' or 'branches'"); +	printerr("        calls              'calls' => create calls and call_paths table"); +	printerr("        callchains         'callchains' => create call_paths table"); +	printerr("        pyside-version-1   'pyside-version-1' => use pyside version 1"); +	raise Exception("Too few or bad arguments")  if (len(sys.argv) < 2):  	usage() @@ -95,6 +125,8 @@ for i in range(3,len(sys.argv)):  		perf_db_export_calls = True  	elif (sys.argv[i] == "callchains"):  		perf_db_export_callchains = True +	elif (sys.argv[i] == "pyside-version-1"): +		pass  	else:  		usage() @@ -186,7 +218,9 @@ if branches:  		'to_ip		bigint,'  		'branch_type	integer,'  		'in_tx		boolean,' -		'call_path_id	bigint)') +		'call_path_id	bigint,' +		'insn_count	bigint,' +		'cyc_count	bigint)')  else:  	do_query(query, 'CREATE TABLE samples ('  		'id		integer		NOT NULL	PRIMARY KEY,' @@ -210,7 +244,9 @@ else:  		'data_src	bigint,'  		'branch_type	integer,'  		'in_tx		boolean,' -		'call_path_id	bigint)') +		'call_path_id	bigint,' +		'insn_count	bigint,' +		'cyc_count	bigint)')  if perf_db_export_calls or perf_db_export_callchains:  	do_query(query, 'CREATE TABLE call_paths (' @@ -231,7 +267,41 @@ if perf_db_export_calls:  		'return_id	bigint,'  		'parent_call_path_id	bigint,'  		'flags		integer,' -		'parent_id	bigint)') +		'parent_id	bigint,' +		'insn_count	bigint,' +		'cyc_count	bigint)') + +do_query(query, 'CREATE TABLE ptwrite (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'payload	bigint,' +		'exact_ip	integer)') + +do_query(query, 'CREATE TABLE cbr (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'cbr		integer,' +		'mhz		integer,' +		'percent	integer)') + +do_query(query, 'CREATE TABLE mwait (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'hints		integer,' +		'extensions	integer)') + +do_query(query, 'CREATE TABLE pwre (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'cstate		integer,' +		'subcstate	integer,' +		'hw		integer)') + +do_query(query, 'CREATE TABLE exstop (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'exact_ip	integer)') + +do_query(query, 'CREATE TABLE pwrx (' +		'id		integer		NOT NULL	PRIMARY KEY,' +		'deepest_cstate	integer,' +		'last_cstate	integer,' +		'wake_reason	integer)')  # printf was added to sqlite in version 3.8.3  sqlite_has_printf = False @@ -327,6 +397,9 @@ if perf_db_export_calls:  			'return_time,'  			'return_time - call_time AS elapsed_time,'  			'branch_count,' +			'insn_count,' +			'cyc_count,' +			'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'  			'call_id,'  			'return_id,'  			'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,' @@ -352,9 +425,108 @@ do_query(query, 'CREATE VIEW samples_view AS '  		'to_sym_offset,'  		'(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'  		'(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,' -		'in_tx' +		'in_tx,' +		'insn_count,' +		'cyc_count,' +		'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC'  	' FROM samples') +do_query(query, 'CREATE VIEW ptwrite_view AS ' +	'SELECT ' +		'ptwrite.id,' +		'time,' +		'cpu,' +		+ emit_to_hex('payload') + ' AS payload_hex,' +		'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip' +	' FROM ptwrite' +	' INNER JOIN samples ON samples.id = ptwrite.id') + +do_query(query, 'CREATE VIEW cbr_view AS ' +	'SELECT ' +		'cbr.id,' +		'time,' +		'cpu,' +		'cbr,' +		'mhz,' +		'percent' +	' FROM cbr' +	' INNER JOIN samples ON samples.id = cbr.id') + +do_query(query, 'CREATE VIEW mwait_view AS ' +	'SELECT ' +		'mwait.id,' +		'time,' +		'cpu,' +		+ emit_to_hex('hints') + ' AS hints_hex,' +		+ emit_to_hex('extensions') + ' AS extensions_hex' +	' FROM mwait' +	' INNER JOIN samples ON samples.id = mwait.id') + +do_query(query, 'CREATE VIEW pwre_view AS ' +	'SELECT ' +		'pwre.id,' +		'time,' +		'cpu,' +		'cstate,' +		'subcstate,' +		'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw' +	' FROM pwre' +	' INNER JOIN samples ON samples.id = pwre.id') + +do_query(query, 'CREATE VIEW exstop_view AS ' +	'SELECT ' +		'exstop.id,' +		'time,' +		'cpu,' +		'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip' +	' FROM exstop' +	' INNER JOIN samples ON samples.id = exstop.id') + +do_query(query, 'CREATE VIEW pwrx_view AS ' +	'SELECT ' +		'pwrx.id,' +		'time,' +		'cpu,' +		'deepest_cstate,' +		'last_cstate,' +		'CASE     WHEN wake_reason=1 THEN \'Interrupt\'' +			' WHEN wake_reason=2 THEN \'Timer Deadline\'' +			' WHEN wake_reason=4 THEN \'Monitored Address\'' +			' WHEN wake_reason=8 THEN \'HW\'' +			' ELSE wake_reason ' +		'END AS wake_reason' +	' FROM pwrx' +	' INNER JOIN samples ON samples.id = pwrx.id') + +do_query(query, 'CREATE VIEW power_events_view AS ' +	'SELECT ' +		'samples.id,' +		'time,' +		'cpu,' +		'selected_events.name AS event,' +		'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,' +		'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,' +		'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,' +		'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,' +		'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,' +		'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,' +		'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,' +		'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,' +		'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,' +		'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,' +		'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,' +		'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT ' +			'CASE     WHEN wake_reason=1 THEN \'Interrupt\'' +				' WHEN wake_reason=2 THEN \'Timer Deadline\'' +				' WHEN wake_reason=4 THEN \'Monitored Address\'' +				' WHEN wake_reason=8 THEN \'HW\'' +				' ELSE wake_reason ' +			'END' +		' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason' +	' FROM samples' +	' INNER JOIN selected_events ON selected_events.id = evsel_id' +	' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')') +  do_query(query, 'END TRANSACTION')  evsel_query = QSqlQuery(db) @@ -375,15 +547,27 @@ branch_type_query = QSqlQuery(db)  branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")  sample_query = QSqlQuery(db)  if branches: -	sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") +	sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")  else: -	sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") +	sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")  if perf_db_export_calls or perf_db_export_callchains:  	call_path_query = QSqlQuery(db)  	call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")  if perf_db_export_calls:  	call_query = QSqlQuery(db) -	call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") +	call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") +ptwrite_query = QSqlQuery(db) +ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)") +cbr_query = QSqlQuery(db) +cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)") +mwait_query = QSqlQuery(db) +mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)") +pwre_query = QSqlQuery(db) +pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)") +exstop_query = QSqlQuery(db) +exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)") +pwrx_query = QSqlQuery(db) +pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")  def trace_begin():  	printdate("Writing records...") @@ -395,13 +579,23 @@ def trace_begin():  	comm_table(0, "unknown")  	dso_table(0, 0, "unknown", "unknown", "")  	symbol_table(0, 0, 0, 0, 0, "unknown") -	sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +	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)  	if perf_db_export_calls or perf_db_export_callchains:  		call_path_table(0, 0, 0, 0) -		call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +		call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)  unhandled_count = 0 +def is_table_empty(table_name): +	do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1'); +	if query.next(): +		return False +	return True + +def drop(table_name): +	do_query(query, 'DROP VIEW ' + table_name + '_view'); +	do_query(query, 'DROP TABLE ' + table_name); +  def trace_end():  	do_query(query, 'END TRANSACTION') @@ -410,6 +604,18 @@ def trace_end():  		do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')  		do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') +	printdate("Dropping unused tables") +	if is_table_empty("ptwrite"): +		drop("ptwrite") +	if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"): +		drop("mwait") +		drop("pwre") +		drop("exstop") +		drop("pwrx") +		do_query(query, 'DROP VIEW power_events_view'); +		if is_table_empty("cbr"): +			drop("cbr") +  	if (unhandled_count):  		printdate("Warning: ", unhandled_count, " unhandled events")  	printdate("Done") @@ -454,14 +660,91 @@ def sample_table(*x):  	if branches:  		for xx in x[0:15]:  			sample_query.addBindValue(str(xx)) -		for xx in x[19:22]: +		for xx in x[19:24]:  			sample_query.addBindValue(str(xx))  		do_query_(sample_query)  	else: -		bind_exec(sample_query, 22, x) +		bind_exec(sample_query, 24, x)  def call_path_table(*x):  	bind_exec(call_path_query, 4, x)  def call_return_table(*x): -	bind_exec(call_query, 12, x) +	bind_exec(call_query, 14, x) + +def ptwrite(id, raw_buf): +	data = struct.unpack_from("<IQ", raw_buf) +	flags = data[0] +	payload = data[1] +	exact_ip = flags & 1 +	ptwrite_query.addBindValue(str(id)) +	ptwrite_query.addBindValue(str(payload)) +	ptwrite_query.addBindValue(str(exact_ip)) +	do_query_(ptwrite_query) + +def cbr(id, raw_buf): +	data = struct.unpack_from("<BBBBII", raw_buf) +	cbr = data[0] +	MHz = (data[4] + 500) / 1000 +	percent = ((cbr * 1000 / data[2]) + 5) / 10 +	cbr_query.addBindValue(str(id)) +	cbr_query.addBindValue(str(cbr)) +	cbr_query.addBindValue(str(MHz)) +	cbr_query.addBindValue(str(percent)) +	do_query_(cbr_query) + +def mwait(id, raw_buf): +	data = struct.unpack_from("<IQ", raw_buf) +	payload = data[1] +	hints = payload & 0xff +	extensions = (payload >> 32) & 0x3 +	mwait_query.addBindValue(str(id)) +	mwait_query.addBindValue(str(hints)) +	mwait_query.addBindValue(str(extensions)) +	do_query_(mwait_query) + +def pwre(id, raw_buf): +	data = struct.unpack_from("<IQ", raw_buf) +	payload = data[1] +	hw = (payload >> 7) & 1 +	cstate = (payload >> 12) & 0xf +	subcstate = (payload >> 8) & 0xf +	pwre_query.addBindValue(str(id)) +	pwre_query.addBindValue(str(cstate)) +	pwre_query.addBindValue(str(subcstate)) +	pwre_query.addBindValue(str(hw)) +	do_query_(pwre_query) + +def exstop(id, raw_buf): +	data = struct.unpack_from("<I", raw_buf) +	flags = data[0] +	exact_ip = flags & 1 +	exstop_query.addBindValue(str(id)) +	exstop_query.addBindValue(str(exact_ip)) +	do_query_(exstop_query) + +def pwrx(id, raw_buf): +	data = struct.unpack_from("<IQ", raw_buf) +	payload = data[1] +	deepest_cstate = payload & 0xf +	last_cstate = (payload >> 4) & 0xf +	wake_reason = (payload >> 8) & 0xf +	pwrx_query.addBindValue(str(id)) +	pwrx_query.addBindValue(str(deepest_cstate)) +	pwrx_query.addBindValue(str(last_cstate)) +	pwrx_query.addBindValue(str(wake_reason)) +	do_query_(pwrx_query) + +def synth_data(id, config, raw_buf, *x): +	if config == 0: +		ptwrite(id, raw_buf) +	elif config == 1: +		mwait(id, raw_buf) +	elif config == 2: +		pwre(id, raw_buf) +	elif config == 3: +		exstop(id, raw_buf) +	elif config == 4: +		pwrx(id, raw_buf) +	elif config == 5: +		cbr(id, raw_buf) | 
