diff options
Diffstat (limited to 'tools/perf/scripts/python/export-to-postgresql.py')
-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,' |