diff options
| author | Adrian Hunter <adrian.hunter@intel.com> | 2015-09-25 09:15:38 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-09-28 15:53:07 -0400 |
| commit | 35ca01c117da9b8e5b60204f730cdde414735596 (patch) | |
| tree | d6a0d8cd22dea54d53cc53c7f42c21da0151c39d /tools/perf/scripts/python | |
| parent | a38f48e300f9dac30a9b2d2ce958c8dbd7def351 (diff) | |
perf tools: Add more documentation to export-to-postgresql.py script
Add some comments to the script and some 'views' to the created database
that better illustrate the database structure and how it can be used.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-8-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/scripts/python')
| -rw-r--r-- | tools/perf/scripts/python/export-to-postgresql.py | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 84a32037a80f..1b02cdc0cab6 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py | |||
| @@ -61,6 +61,142 @@ import datetime | |||
| 61 | # | 61 | # |
| 62 | # An example of using the database is provided by the script | 62 | # An example of using the database is provided by the script |
| 63 | # call-graph-from-postgresql.py. Refer to that script for details. | 63 | # call-graph-from-postgresql.py. Refer to that script for details. |
| 64 | # | ||
| 65 | # Tables: | ||
| 66 | # | ||
| 67 | # The tables largely correspond to perf tools' data structures. They are largely self-explanatory. | ||
| 68 | # | ||
| 69 | # samples | ||
| 70 | # | ||
| 71 | # 'samples' is the main table. It represents what instruction was executing at a point in time | ||
| 72 | # when something (a selected event) happened. The memory address is the instruction pointer or 'ip'. | ||
| 73 | # | ||
| 74 | # calls | ||
| 75 | # | ||
| 76 | # 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'. | ||
| 77 | # 'calls' is only created when the 'calls' option to this script is specified. | ||
| 78 | # | ||
| 79 | # call_paths | ||
| 80 | # | ||
| 81 | # 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'. | ||
| 82 | # 'calls_paths' is only created when the 'calls' option to this script is specified. | ||
| 83 | # | ||
| 84 | # branch_types | ||
| 85 | # | ||
| 86 | # 'branch_types' provides descriptions for each type of branch. | ||
| 87 | # | ||
| 88 | # comm_threads | ||
| 89 | # | ||
| 90 | # 'comm_threads' shows how 'comms' relates to 'threads'. | ||
| 91 | # | ||
| 92 | # comms | ||
| 93 | # | ||
| 94 | # 'comms' contains a record for each 'comm' - the name given to the executable that is running. | ||
| 95 | # | ||
| 96 | # dsos | ||
| 97 | # | ||
| 98 | # 'dsos' contains a record for each executable file or library. | ||
| 99 | # | ||
| 100 | # machines | ||
| 101 | # | ||
| 102 | # 'machines' can be used to distinguish virtual machines if virtualization is supported. | ||
| 103 | # | ||
| 104 | # selected_events | ||
| 105 | # | ||
| 106 | # 'selected_events' contains a record for each kind of event that has been sampled. | ||
| 107 | # | ||
| 108 | # symbols | ||
| 109 | # | ||
| 110 | # 'symbols' contains a record for each symbol. Only symbols that have samples are present. | ||
| 111 | # | ||
| 112 | # threads | ||
| 113 | # | ||
| 114 | # 'threads' contains a record for each thread. | ||
| 115 | # | ||
| 116 | # Views: | ||
| 117 | # | ||
| 118 | # Most of the tables have views for more friendly display. The views are: | ||
| 119 | # | ||
| 120 | # calls_view | ||
| 121 | # call_paths_view | ||
| 122 | # comm_threads_view | ||
| 123 | # dsos_view | ||
| 124 | # machines_view | ||
| 125 | # samples_view | ||
| 126 | # symbols_view | ||
| 127 | # threads_view | ||
| 128 | # | ||
| 129 | # More examples of browsing the database with psql: | ||
| 130 | # Note that some of the examples are not the most optimal SQL query. | ||
| 131 | # Note that call information is only available if the script's 'calls' option has been used. | ||
| 132 | # | ||
| 133 | # Top 10 function calls (not aggregated by symbol): | ||
| 134 | # | ||
| 135 | # SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10; | ||
| 136 | # | ||
| 137 | # Top 10 function calls (aggregated by symbol): | ||
| 138 | # | ||
| 139 | # SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol, | ||
| 140 | # SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count | ||
| 141 | # FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10; | ||
| 142 | # | ||
| 143 | # Note that the branch count gives a rough estimation of cpu usage, so functions | ||
| 144 | # that took a long time but have a relatively low branch count must have spent time | ||
| 145 | # waiting. | ||
| 146 | # | ||
| 147 | # Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'): | ||
| 148 | # | ||
| 149 | # SELECT * FROM symbols_view WHERE name LIKE '%alloc%'; | ||
| 150 | # | ||
| 151 | # Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187): | ||
| 152 | # | ||
| 153 | # SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10; | ||
| 154 | # | ||
| 155 | # Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254): | ||
| 156 | # | ||
| 157 | # SELECT * FROM calls_view WHERE parent_call_path_id = 254; | ||
| 158 | # | ||
| 159 | # Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670) | ||
| 160 | # | ||
| 161 | # SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%'; | ||
| 162 | # | ||
| 163 | # Show transactions: | ||
| 164 | # | ||
| 165 | # SELECT * FROM samples_view WHERE event = 'transactions'; | ||
| 166 | # | ||
| 167 | # Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false. | ||
| 168 | # Transaction aborts have branch_type_name 'transaction abort' | ||
| 169 | # | ||
| 170 | # Show transaction aborts: | ||
| 171 | # | ||
| 172 | # SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort'; | ||
| 173 | # | ||
| 174 | # To print a call stack requires walking the call_paths table. For example this python script: | ||
| 175 | # #!/usr/bin/python2 | ||
| 176 | # | ||
| 177 | # import sys | ||
| 178 | # from PySide.QtSql import * | ||
| 179 | # | ||
| 180 | # if __name__ == '__main__': | ||
| 181 | # if (len(sys.argv) < 3): | ||
| 182 | # print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>" | ||
| 183 | # raise Exception("Too few arguments") | ||
| 184 | # dbname = sys.argv[1] | ||
| 185 | # call_path_id = sys.argv[2] | ||
| 186 | # db = QSqlDatabase.addDatabase('QPSQL') | ||
| 187 | # db.setDatabaseName(dbname) | ||
| 188 | # if not db.open(): | ||
| 189 | # raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text()) | ||
| 190 | # query = QSqlQuery(db) | ||
| 191 | # print " id ip symbol_id symbol dso_id dso_short_name" | ||
| 192 | # while call_path_id != 0 and call_path_id != 1: | ||
| 193 | # ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id)) | ||
| 194 | # if not ret: | ||
| 195 | # raise Exception("Query failed: " + query.lastError().text()) | ||
| 196 | # if not query.next(): | ||
| 197 | # raise Exception("Query failed") | ||
| 198 | # print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5)) | ||
| 199 | # call_path_id = query.value(6) | ||
| 64 | 200 | ||
| 65 | from PySide.QtSql import * | 201 | from PySide.QtSql import * |
| 66 | 202 | ||
| @@ -244,6 +380,91 @@ if perf_db_export_calls: | |||
| 244 | 'parent_call_path_id bigint,' | 380 | 'parent_call_path_id bigint,' |
| 245 | 'flags integer)') | 381 | 'flags integer)') |
| 246 | 382 | ||
| 383 | do_query(query, 'CREATE VIEW machines_view AS ' | ||
| 384 | 'SELECT ' | ||
| 385 | 'id,' | ||
| 386 | 'pid,' | ||
| 387 | 'root_dir,' | ||
| 388 | 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest' | ||
| 389 | ' FROM machines') | ||
| 390 | |||
| 391 | do_query(query, 'CREATE VIEW dsos_view AS ' | ||
| 392 | 'SELECT ' | ||
| 393 | 'id,' | ||
| 394 | 'machine_id,' | ||
| 395 | '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,' | ||
| 396 | 'short_name,' | ||
| 397 | 'long_name,' | ||
| 398 | 'build_id' | ||
| 399 | ' FROM dsos') | ||
| 400 | |||
| 401 | do_query(query, 'CREATE VIEW symbols_view AS ' | ||
| 402 | 'SELECT ' | ||
| 403 | 'id,' | ||
| 404 | 'name,' | ||
| 405 | '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,' | ||
| 406 | 'dso_id,' | ||
| 407 | 'sym_start,' | ||
| 408 | 'sym_end,' | ||
| 409 | 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding' | ||
| 410 | ' FROM symbols') | ||
| 411 | |||
| 412 | do_query(query, 'CREATE VIEW threads_view AS ' | ||
| 413 | 'SELECT ' | ||
| 414 | 'id,' | ||
| 415 | 'machine_id,' | ||
| 416 | '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,' | ||
| 417 | 'process_id,' | ||
| 418 | 'pid,' | ||
| 419 | 'tid' | ||
| 420 | ' FROM threads') | ||
| 421 | |||
| 422 | do_query(query, 'CREATE VIEW comm_threads_view AS ' | ||
| 423 | 'SELECT ' | ||
| 424 | 'comm_id,' | ||
| 425 | '(SELECT comm FROM comms WHERE id = comm_id) AS command,' | ||
| 426 | 'thread_id,' | ||
| 427 | '(SELECT pid FROM threads WHERE id = thread_id) AS pid,' | ||
| 428 | '(SELECT tid FROM threads WHERE id = thread_id) AS tid' | ||
| 429 | ' FROM comm_threads') | ||
| 430 | |||
| 431 | if perf_db_export_calls: | ||
| 432 | do_query(query, 'CREATE VIEW call_paths_view AS ' | ||
| 433 | 'SELECT ' | ||
| 434 | 'c.id,' | ||
| 435 | 'to_hex(c.ip) AS ip,' | ||
| 436 | 'c.symbol_id,' | ||
| 437 | '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,' | ||
| 438 | '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,' | ||
| 439 | '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,' | ||
| 440 | 'c.parent_id,' | ||
| 441 | 'to_hex(p.ip) AS parent_ip,' | ||
| 442 | 'p.symbol_id AS parent_symbol_id,' | ||
| 443 | '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,' | ||
| 444 | '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,' | ||
| 445 | '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name' | ||
| 446 | ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id') | ||
| 447 | do_query(query, 'CREATE VIEW calls_view AS ' | ||
| 448 | 'SELECT ' | ||
| 449 | 'calls.id,' | ||
| 450 | 'thread_id,' | ||
| 451 | '(SELECT pid FROM threads WHERE id = thread_id) AS pid,' | ||
| 452 | '(SELECT tid FROM threads WHERE id = thread_id) AS tid,' | ||
| 453 | '(SELECT comm FROM comms WHERE id = comm_id) AS command,' | ||
| 454 | 'call_path_id,' | ||
| 455 | 'to_hex(ip) AS ip,' | ||
| 456 | 'symbol_id,' | ||
| 457 | '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,' | ||
| 458 | 'call_time,' | ||
| 459 | 'return_time,' | ||
| 460 | 'return_time - call_time AS elapsed_time,' | ||
| 461 | 'branch_count,' | ||
| 462 | 'call_id,' | ||
| 463 | 'return_id,' | ||
| 464 | 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' | ||
| 465 | 'parent_call_path_id' | ||
| 466 | ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') | ||
| 467 | |||
| 247 | do_query(query, 'CREATE VIEW samples_view AS ' | 468 | do_query(query, 'CREATE VIEW samples_view AS ' |
| 248 | 'SELECT ' | 469 | 'SELECT ' |
| 249 | 'id,' | 470 | 'id,' |
