.. | .. |
---|
10 | 10 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
11 | 11 | # more details. |
---|
12 | 12 | |
---|
| 13 | +from __future__ import print_function |
---|
| 14 | + |
---|
13 | 15 | import os |
---|
14 | 16 | import sys |
---|
15 | 17 | import struct |
---|
.. | .. |
---|
25 | 27 | # |
---|
26 | 28 | # fedora: |
---|
27 | 29 | # |
---|
28 | | -# $ sudo yum install postgresql postgresql-server python-pyside qt-postgresql |
---|
| 30 | +# $ sudo yum install postgresql postgresql-server qt-postgresql |
---|
29 | 31 | # $ sudo su - postgres -c initdb |
---|
30 | 32 | # $ sudo service postgresql start |
---|
31 | 33 | # $ sudo su - postgres |
---|
32 | | -# $ createuser <your user id here> |
---|
| 34 | +# $ createuser -s <your user id here> # Older versions may not support -s, in which case answer the prompt below: |
---|
33 | 35 | # Shall the new role be a superuser? (y/n) y |
---|
| 36 | +# $ sudo yum install python-pyside |
---|
| 37 | +# |
---|
| 38 | +# Alternately, to use Python3 and/or pyside 2, one of the following: |
---|
| 39 | +# $ sudo yum install python3-pyside |
---|
| 40 | +# $ pip install --user PySide2 |
---|
| 41 | +# $ pip3 install --user PySide2 |
---|
34 | 42 | # |
---|
35 | 43 | # ubuntu: |
---|
36 | 44 | # |
---|
37 | | -# $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql |
---|
| 45 | +# $ sudo apt-get install postgresql |
---|
38 | 46 | # $ sudo su - postgres |
---|
39 | 47 | # $ createuser -s <your user id here> |
---|
| 48 | +# $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql |
---|
| 49 | +# |
---|
| 50 | +# Alternately, to use Python3 and/or pyside 2, one of the following: |
---|
| 51 | +# |
---|
| 52 | +# $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql |
---|
| 53 | +# $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql |
---|
| 54 | +# $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql |
---|
40 | 55 | # |
---|
41 | 56 | # An example of using this script with Intel PT: |
---|
42 | 57 | # |
---|
.. | .. |
---|
59 | 74 | # pt_example=# \q |
---|
60 | 75 | # |
---|
61 | 76 | # An example of using the database is provided by the script |
---|
62 | | -# call-graph-from-sql.py. Refer to that script for details. |
---|
| 77 | +# exported-sql-viewer.py. Refer to that script for details. |
---|
63 | 78 | # |
---|
64 | 79 | # Tables: |
---|
65 | 80 | # |
---|
.. | .. |
---|
197 | 212 | # 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)) |
---|
198 | 213 | # call_path_id = query.value(6) |
---|
199 | 214 | |
---|
200 | | -from PySide.QtSql import * |
---|
| 215 | +pyside_version_1 = True |
---|
| 216 | +if not "pyside-version-1" in sys.argv: |
---|
| 217 | + try: |
---|
| 218 | + from PySide2.QtSql import * |
---|
| 219 | + pyside_version_1 = False |
---|
| 220 | + except: |
---|
| 221 | + pass |
---|
| 222 | + |
---|
| 223 | +if pyside_version_1: |
---|
| 224 | + from PySide.QtSql import * |
---|
| 225 | + |
---|
| 226 | +if sys.version_info < (3, 0): |
---|
| 227 | + def toserverstr(str): |
---|
| 228 | + return str |
---|
| 229 | + def toclientstr(str): |
---|
| 230 | + return str |
---|
| 231 | +else: |
---|
| 232 | + # Assume UTF-8 server_encoding and client_encoding |
---|
| 233 | + def toserverstr(str): |
---|
| 234 | + return bytes(str, "UTF_8") |
---|
| 235 | + def toclientstr(str): |
---|
| 236 | + return bytes(str, "UTF_8") |
---|
201 | 237 | |
---|
202 | 238 | # Need to access PostgreSQL C library directly to use COPY FROM STDIN |
---|
203 | 239 | from ctypes import * |
---|
.. | .. |
---|
234 | 270 | perf_db_export_calls = False |
---|
235 | 271 | perf_db_export_callchains = False |
---|
236 | 272 | |
---|
| 273 | +def printerr(*args, **kw_args): |
---|
| 274 | + print(*args, file=sys.stderr, **kw_args) |
---|
| 275 | + |
---|
| 276 | +def printdate(*args, **kw_args): |
---|
| 277 | + print(datetime.datetime.today(), *args, sep=' ', **kw_args) |
---|
237 | 278 | |
---|
238 | 279 | def usage(): |
---|
239 | | - print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]" |
---|
240 | | - print >> sys.stderr, "where: columns 'all' or 'branches'" |
---|
241 | | - print >> sys.stderr, " calls 'calls' => create calls and call_paths table" |
---|
242 | | - print >> sys.stderr, " callchains 'callchains' => create call_paths table" |
---|
243 | | - raise Exception("Too few arguments") |
---|
| 280 | + printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]"); |
---|
| 281 | + printerr("where: columns 'all' or 'branches'"); |
---|
| 282 | + printerr(" calls 'calls' => create calls and call_paths table"); |
---|
| 283 | + printerr(" callchains 'callchains' => create call_paths table"); |
---|
| 284 | + printerr(" pyside-version-1 'pyside-version-1' => use pyside version 1"); |
---|
| 285 | + raise Exception("Too few or bad arguments") |
---|
244 | 286 | |
---|
245 | 287 | if (len(sys.argv) < 2): |
---|
246 | 288 | usage() |
---|
.. | .. |
---|
262 | 304 | perf_db_export_calls = True |
---|
263 | 305 | elif (sys.argv[i] == "callchains"): |
---|
264 | 306 | perf_db_export_callchains = True |
---|
| 307 | + elif (sys.argv[i] == "pyside-version-1"): |
---|
| 308 | + pass |
---|
265 | 309 | else: |
---|
266 | 310 | usage() |
---|
267 | 311 | |
---|
.. | .. |
---|
273 | 317 | return |
---|
274 | 318 | raise Exception("Query failed: " + q.lastError().text()) |
---|
275 | 319 | |
---|
276 | | -print datetime.datetime.today(), "Creating database..." |
---|
| 320 | +printdate("Creating database...") |
---|
277 | 321 | |
---|
278 | 322 | db = QSqlDatabase.addDatabase('QPSQL') |
---|
279 | 323 | query = QSqlQuery(db) |
---|
.. | .. |
---|
309 | 353 | 'tid integer)') |
---|
310 | 354 | do_query(query, 'CREATE TABLE comms (' |
---|
311 | 355 | 'id bigint NOT NULL,' |
---|
312 | | - 'comm varchar(16))') |
---|
| 356 | + 'comm varchar(16),' |
---|
| 357 | + 'c_thread_id bigint,' |
---|
| 358 | + 'c_time bigint,' |
---|
| 359 | + 'exec_flag boolean)') |
---|
313 | 360 | do_query(query, 'CREATE TABLE comm_threads (' |
---|
314 | 361 | 'id bigint NOT NULL,' |
---|
315 | 362 | 'comm_id bigint,' |
---|
.. | .. |
---|
350 | 397 | 'to_ip bigint,' |
---|
351 | 398 | 'branch_type integer,' |
---|
352 | 399 | 'in_tx boolean,' |
---|
353 | | - 'call_path_id bigint)') |
---|
| 400 | + 'call_path_id bigint,' |
---|
| 401 | + 'insn_count bigint,' |
---|
| 402 | + 'cyc_count bigint)') |
---|
354 | 403 | else: |
---|
355 | 404 | do_query(query, 'CREATE TABLE samples (' |
---|
356 | 405 | 'id bigint NOT NULL,' |
---|
.. | .. |
---|
374 | 423 | 'data_src bigint,' |
---|
375 | 424 | 'branch_type integer,' |
---|
376 | 425 | 'in_tx boolean,' |
---|
377 | | - 'call_path_id bigint)') |
---|
| 426 | + 'call_path_id bigint,' |
---|
| 427 | + 'insn_count bigint,' |
---|
| 428 | + 'cyc_count bigint)') |
---|
378 | 429 | |
---|
379 | 430 | if perf_db_export_calls or perf_db_export_callchains: |
---|
380 | 431 | do_query(query, 'CREATE TABLE call_paths (' |
---|
.. | .. |
---|
394 | 445 | 'call_id bigint,' |
---|
395 | 446 | 'return_id bigint,' |
---|
396 | 447 | 'parent_call_path_id bigint,' |
---|
| 448 | + 'flags integer,' |
---|
| 449 | + 'parent_id bigint,' |
---|
| 450 | + 'insn_count bigint,' |
---|
| 451 | + 'cyc_count bigint)') |
---|
| 452 | + |
---|
| 453 | +do_query(query, 'CREATE TABLE ptwrite (' |
---|
| 454 | + 'id bigint NOT NULL,' |
---|
| 455 | + 'payload bigint,' |
---|
| 456 | + 'exact_ip boolean)') |
---|
| 457 | + |
---|
| 458 | +do_query(query, 'CREATE TABLE cbr (' |
---|
| 459 | + 'id bigint NOT NULL,' |
---|
| 460 | + 'cbr integer,' |
---|
| 461 | + 'mhz integer,' |
---|
| 462 | + 'percent integer)') |
---|
| 463 | + |
---|
| 464 | +do_query(query, 'CREATE TABLE mwait (' |
---|
| 465 | + 'id bigint NOT NULL,' |
---|
| 466 | + 'hints integer,' |
---|
| 467 | + 'extensions integer)') |
---|
| 468 | + |
---|
| 469 | +do_query(query, 'CREATE TABLE pwre (' |
---|
| 470 | + 'id bigint NOT NULL,' |
---|
| 471 | + 'cstate integer,' |
---|
| 472 | + 'subcstate integer,' |
---|
| 473 | + 'hw boolean)') |
---|
| 474 | + |
---|
| 475 | +do_query(query, 'CREATE TABLE exstop (' |
---|
| 476 | + 'id bigint NOT NULL,' |
---|
| 477 | + 'exact_ip boolean)') |
---|
| 478 | + |
---|
| 479 | +do_query(query, 'CREATE TABLE pwrx (' |
---|
| 480 | + 'id bigint NOT NULL,' |
---|
| 481 | + 'deepest_cstate integer,' |
---|
| 482 | + 'last_cstate integer,' |
---|
| 483 | + 'wake_reason integer)') |
---|
| 484 | + |
---|
| 485 | +do_query(query, 'CREATE TABLE context_switches (' |
---|
| 486 | + 'id bigint NOT NULL,' |
---|
| 487 | + 'machine_id bigint,' |
---|
| 488 | + 'time bigint,' |
---|
| 489 | + 'cpu integer,' |
---|
| 490 | + 'thread_out_id bigint,' |
---|
| 491 | + 'comm_out_id bigint,' |
---|
| 492 | + 'thread_in_id bigint,' |
---|
| 493 | + 'comm_in_id bigint,' |
---|
397 | 494 | 'flags integer)') |
---|
398 | 495 | |
---|
399 | 496 | do_query(query, 'CREATE VIEW machines_view AS ' |
---|
.. | .. |
---|
476 | 573 | 'return_time,' |
---|
477 | 574 | 'return_time - call_time AS elapsed_time,' |
---|
478 | 575 | 'branch_count,' |
---|
| 576 | + 'insn_count,' |
---|
| 577 | + 'cyc_count,' |
---|
| 578 | + 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC,' |
---|
479 | 579 | 'call_id,' |
---|
480 | 580 | 'return_id,' |
---|
481 | | - 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' |
---|
482 | | - 'parent_call_path_id' |
---|
| 581 | + '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 CAST ( flags AS VARCHAR(6) ) END AS flags,' |
---|
| 582 | + 'parent_call_path_id,' |
---|
| 583 | + 'calls.parent_id' |
---|
483 | 584 | ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') |
---|
484 | 585 | |
---|
485 | 586 | do_query(query, 'CREATE VIEW samples_view AS ' |
---|
.. | .. |
---|
500 | 601 | 'to_sym_offset,' |
---|
501 | 602 | '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,' |
---|
502 | 603 | '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,' |
---|
503 | | - 'in_tx' |
---|
| 604 | + 'in_tx,' |
---|
| 605 | + 'insn_count,' |
---|
| 606 | + 'cyc_count,' |
---|
| 607 | + 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC' |
---|
504 | 608 | ' FROM samples') |
---|
505 | 609 | |
---|
| 610 | +do_query(query, 'CREATE VIEW ptwrite_view AS ' |
---|
| 611 | + 'SELECT ' |
---|
| 612 | + 'ptwrite.id,' |
---|
| 613 | + 'time,' |
---|
| 614 | + 'cpu,' |
---|
| 615 | + 'to_hex(payload) AS payload_hex,' |
---|
| 616 | + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' |
---|
| 617 | + ' FROM ptwrite' |
---|
| 618 | + ' INNER JOIN samples ON samples.id = ptwrite.id') |
---|
506 | 619 | |
---|
507 | | -file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0) |
---|
508 | | -file_trailer = "\377\377" |
---|
| 620 | +do_query(query, 'CREATE VIEW cbr_view AS ' |
---|
| 621 | + 'SELECT ' |
---|
| 622 | + 'cbr.id,' |
---|
| 623 | + 'time,' |
---|
| 624 | + 'cpu,' |
---|
| 625 | + 'cbr,' |
---|
| 626 | + 'mhz,' |
---|
| 627 | + 'percent' |
---|
| 628 | + ' FROM cbr' |
---|
| 629 | + ' INNER JOIN samples ON samples.id = cbr.id') |
---|
| 630 | + |
---|
| 631 | +do_query(query, 'CREATE VIEW mwait_view AS ' |
---|
| 632 | + 'SELECT ' |
---|
| 633 | + 'mwait.id,' |
---|
| 634 | + 'time,' |
---|
| 635 | + 'cpu,' |
---|
| 636 | + 'to_hex(hints) AS hints_hex,' |
---|
| 637 | + 'to_hex(extensions) AS extensions_hex' |
---|
| 638 | + ' FROM mwait' |
---|
| 639 | + ' INNER JOIN samples ON samples.id = mwait.id') |
---|
| 640 | + |
---|
| 641 | +do_query(query, 'CREATE VIEW pwre_view AS ' |
---|
| 642 | + 'SELECT ' |
---|
| 643 | + 'pwre.id,' |
---|
| 644 | + 'time,' |
---|
| 645 | + 'cpu,' |
---|
| 646 | + 'cstate,' |
---|
| 647 | + 'subcstate,' |
---|
| 648 | + 'CASE WHEN hw=FALSE THEN \'False\' ELSE \'True\' END AS hw' |
---|
| 649 | + ' FROM pwre' |
---|
| 650 | + ' INNER JOIN samples ON samples.id = pwre.id') |
---|
| 651 | + |
---|
| 652 | +do_query(query, 'CREATE VIEW exstop_view AS ' |
---|
| 653 | + 'SELECT ' |
---|
| 654 | + 'exstop.id,' |
---|
| 655 | + 'time,' |
---|
| 656 | + 'cpu,' |
---|
| 657 | + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' |
---|
| 658 | + ' FROM exstop' |
---|
| 659 | + ' INNER JOIN samples ON samples.id = exstop.id') |
---|
| 660 | + |
---|
| 661 | +do_query(query, 'CREATE VIEW pwrx_view AS ' |
---|
| 662 | + 'SELECT ' |
---|
| 663 | + 'pwrx.id,' |
---|
| 664 | + 'time,' |
---|
| 665 | + 'cpu,' |
---|
| 666 | + 'deepest_cstate,' |
---|
| 667 | + 'last_cstate,' |
---|
| 668 | + 'CASE WHEN wake_reason=1 THEN \'Interrupt\'' |
---|
| 669 | + ' WHEN wake_reason=2 THEN \'Timer Deadline\'' |
---|
| 670 | + ' WHEN wake_reason=4 THEN \'Monitored Address\'' |
---|
| 671 | + ' WHEN wake_reason=8 THEN \'HW\'' |
---|
| 672 | + ' ELSE CAST ( wake_reason AS VARCHAR(2) )' |
---|
| 673 | + 'END AS wake_reason' |
---|
| 674 | + ' FROM pwrx' |
---|
| 675 | + ' INNER JOIN samples ON samples.id = pwrx.id') |
---|
| 676 | + |
---|
| 677 | +do_query(query, 'CREATE VIEW power_events_view AS ' |
---|
| 678 | + 'SELECT ' |
---|
| 679 | + 'samples.id,' |
---|
| 680 | + 'samples.time,' |
---|
| 681 | + 'samples.cpu,' |
---|
| 682 | + 'selected_events.name AS event,' |
---|
| 683 | + 'FORMAT(\'%6s\', cbr.cbr) AS cbr,' |
---|
| 684 | + 'FORMAT(\'%6s\', cbr.mhz) AS MHz,' |
---|
| 685 | + 'FORMAT(\'%5s\', cbr.percent) AS percent,' |
---|
| 686 | + 'to_hex(mwait.hints) AS hints_hex,' |
---|
| 687 | + 'to_hex(mwait.extensions) AS extensions_hex,' |
---|
| 688 | + 'FORMAT(\'%3s\', pwre.cstate) AS cstate,' |
---|
| 689 | + 'FORMAT(\'%3s\', pwre.subcstate) AS subcstate,' |
---|
| 690 | + 'CASE WHEN pwre.hw=FALSE THEN \'False\' WHEN pwre.hw=TRUE THEN \'True\' ELSE NULL END AS hw,' |
---|
| 691 | + 'CASE WHEN exstop.exact_ip=FALSE THEN \'False\' WHEN exstop.exact_ip=TRUE THEN \'True\' ELSE NULL END AS exact_ip,' |
---|
| 692 | + 'FORMAT(\'%3s\', pwrx.deepest_cstate) AS deepest_cstate,' |
---|
| 693 | + 'FORMAT(\'%3s\', pwrx.last_cstate) AS last_cstate,' |
---|
| 694 | + 'CASE WHEN pwrx.wake_reason=1 THEN \'Interrupt\'' |
---|
| 695 | + ' WHEN pwrx.wake_reason=2 THEN \'Timer Deadline\'' |
---|
| 696 | + ' WHEN pwrx.wake_reason=4 THEN \'Monitored Address\'' |
---|
| 697 | + ' WHEN pwrx.wake_reason=8 THEN \'HW\'' |
---|
| 698 | + ' ELSE FORMAT(\'%2s\', pwrx.wake_reason)' |
---|
| 699 | + 'END AS wake_reason' |
---|
| 700 | + ' FROM cbr' |
---|
| 701 | + ' FULL JOIN mwait ON mwait.id = cbr.id' |
---|
| 702 | + ' FULL JOIN pwre ON pwre.id = cbr.id' |
---|
| 703 | + ' FULL JOIN exstop ON exstop.id = cbr.id' |
---|
| 704 | + ' FULL JOIN pwrx ON pwrx.id = cbr.id' |
---|
| 705 | + ' INNER JOIN samples ON samples.id = coalesce(cbr.id, mwait.id, pwre.id, exstop.id, pwrx.id)' |
---|
| 706 | + ' INNER JOIN selected_events ON selected_events.id = samples.evsel_id' |
---|
| 707 | + ' ORDER BY samples.id') |
---|
| 708 | + |
---|
| 709 | +do_query(query, 'CREATE VIEW context_switches_view AS ' |
---|
| 710 | + 'SELECT ' |
---|
| 711 | + 'context_switches.id,' |
---|
| 712 | + 'context_switches.machine_id,' |
---|
| 713 | + 'context_switches.time,' |
---|
| 714 | + 'context_switches.cpu,' |
---|
| 715 | + 'th_out.pid AS pid_out,' |
---|
| 716 | + 'th_out.tid AS tid_out,' |
---|
| 717 | + 'comm_out.comm AS comm_out,' |
---|
| 718 | + 'th_in.pid AS pid_in,' |
---|
| 719 | + 'th_in.tid AS tid_in,' |
---|
| 720 | + 'comm_in.comm AS comm_in,' |
---|
| 721 | + 'CASE WHEN context_switches.flags = 0 THEN \'in\'' |
---|
| 722 | + ' WHEN context_switches.flags = 1 THEN \'out\'' |
---|
| 723 | + ' WHEN context_switches.flags = 3 THEN \'out preempt\'' |
---|
| 724 | + ' ELSE CAST ( context_switches.flags AS VARCHAR(11) )' |
---|
| 725 | + 'END AS flags' |
---|
| 726 | + ' FROM context_switches' |
---|
| 727 | + ' INNER JOIN threads AS th_out ON th_out.id = context_switches.thread_out_id' |
---|
| 728 | + ' INNER JOIN threads AS th_in ON th_in.id = context_switches.thread_in_id' |
---|
| 729 | + ' INNER JOIN comms AS comm_out ON comm_out.id = context_switches.comm_out_id' |
---|
| 730 | + ' INNER JOIN comms AS comm_in ON comm_in.id = context_switches.comm_in_id') |
---|
| 731 | + |
---|
| 732 | +file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0) |
---|
| 733 | +file_trailer = b"\377\377" |
---|
509 | 734 | |
---|
510 | 735 | def open_output_file(file_name): |
---|
511 | 736 | path_name = output_dir_name + "/" + file_name |
---|
512 | | - file = open(path_name, "w+") |
---|
| 737 | + file = open(path_name, "wb+") |
---|
513 | 738 | file.write(file_header) |
---|
514 | 739 | return file |
---|
515 | 740 | |
---|
.. | .. |
---|
524 | 749 | |
---|
525 | 750 | # Use COPY FROM STDIN because security may prevent postgres from accessing the files directly |
---|
526 | 751 | def copy_output_file(file, table_name): |
---|
527 | | - conn = PQconnectdb("dbname = " + dbname) |
---|
| 752 | + conn = PQconnectdb(toclientstr("dbname = " + dbname)) |
---|
528 | 753 | if (PQstatus(conn)): |
---|
529 | 754 | raise Exception("COPY FROM STDIN PQconnectdb failed") |
---|
530 | 755 | file.write(file_trailer) |
---|
531 | 756 | file.seek(0) |
---|
532 | 757 | sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')" |
---|
533 | | - res = PQexec(conn, sql) |
---|
| 758 | + res = PQexec(conn, toclientstr(sql)) |
---|
534 | 759 | if (PQresultStatus(res) != 4): |
---|
535 | 760 | raise Exception("COPY FROM STDIN PQexec failed") |
---|
536 | 761 | data = file.read(65536) |
---|
.. | .. |
---|
562 | 787 | call_path_file = open_output_file("call_path_table.bin") |
---|
563 | 788 | if perf_db_export_calls: |
---|
564 | 789 | call_file = open_output_file("call_table.bin") |
---|
| 790 | +ptwrite_file = open_output_file("ptwrite_table.bin") |
---|
| 791 | +cbr_file = open_output_file("cbr_table.bin") |
---|
| 792 | +mwait_file = open_output_file("mwait_table.bin") |
---|
| 793 | +pwre_file = open_output_file("pwre_table.bin") |
---|
| 794 | +exstop_file = open_output_file("exstop_table.bin") |
---|
| 795 | +pwrx_file = open_output_file("pwrx_table.bin") |
---|
| 796 | +context_switches_file = open_output_file("context_switches_table.bin") |
---|
565 | 797 | |
---|
566 | 798 | def trace_begin(): |
---|
567 | | - print datetime.datetime.today(), "Writing to intermediate files..." |
---|
| 799 | + printdate("Writing to intermediate files...") |
---|
568 | 800 | # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs |
---|
569 | 801 | evsel_table(0, "unknown") |
---|
570 | 802 | machine_table(0, 0, "unknown") |
---|
571 | 803 | thread_table(0, 0, 0, -1, -1) |
---|
572 | | - comm_table(0, "unknown") |
---|
| 804 | + comm_table(0, "unknown", 0, 0, 0) |
---|
573 | 805 | dso_table(0, 0, "unknown", "unknown", "") |
---|
574 | 806 | symbol_table(0, 0, 0, 0, 0, "unknown") |
---|
575 | | - sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) |
---|
| 807 | + 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) |
---|
576 | 808 | if perf_db_export_calls or perf_db_export_callchains: |
---|
577 | 809 | call_path_table(0, 0, 0, 0) |
---|
| 810 | + call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) |
---|
578 | 811 | |
---|
579 | 812 | unhandled_count = 0 |
---|
580 | 813 | |
---|
| 814 | +def is_table_empty(table_name): |
---|
| 815 | + do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1'); |
---|
| 816 | + if query.next(): |
---|
| 817 | + return False |
---|
| 818 | + return True |
---|
| 819 | + |
---|
| 820 | +def drop(table_name): |
---|
| 821 | + do_query(query, 'DROP VIEW ' + table_name + '_view'); |
---|
| 822 | + do_query(query, 'DROP TABLE ' + table_name); |
---|
| 823 | + |
---|
581 | 824 | def trace_end(): |
---|
582 | | - print datetime.datetime.today(), "Copying to database..." |
---|
| 825 | + printdate("Copying to database...") |
---|
583 | 826 | copy_output_file(evsel_file, "selected_events") |
---|
584 | 827 | copy_output_file(machine_file, "machines") |
---|
585 | 828 | copy_output_file(thread_file, "threads") |
---|
.. | .. |
---|
593 | 836 | copy_output_file(call_path_file, "call_paths") |
---|
594 | 837 | if perf_db_export_calls: |
---|
595 | 838 | copy_output_file(call_file, "calls") |
---|
| 839 | + copy_output_file(ptwrite_file, "ptwrite") |
---|
| 840 | + copy_output_file(cbr_file, "cbr") |
---|
| 841 | + copy_output_file(mwait_file, "mwait") |
---|
| 842 | + copy_output_file(pwre_file, "pwre") |
---|
| 843 | + copy_output_file(exstop_file, "exstop") |
---|
| 844 | + copy_output_file(pwrx_file, "pwrx") |
---|
| 845 | + copy_output_file(context_switches_file, "context_switches") |
---|
596 | 846 | |
---|
597 | | - print datetime.datetime.today(), "Removing intermediate files..." |
---|
| 847 | + printdate("Removing intermediate files...") |
---|
598 | 848 | remove_output_file(evsel_file) |
---|
599 | 849 | remove_output_file(machine_file) |
---|
600 | 850 | remove_output_file(thread_file) |
---|
.. | .. |
---|
608 | 858 | remove_output_file(call_path_file) |
---|
609 | 859 | if perf_db_export_calls: |
---|
610 | 860 | remove_output_file(call_file) |
---|
| 861 | + remove_output_file(ptwrite_file) |
---|
| 862 | + remove_output_file(cbr_file) |
---|
| 863 | + remove_output_file(mwait_file) |
---|
| 864 | + remove_output_file(pwre_file) |
---|
| 865 | + remove_output_file(exstop_file) |
---|
| 866 | + remove_output_file(pwrx_file) |
---|
| 867 | + remove_output_file(context_switches_file) |
---|
611 | 868 | os.rmdir(output_dir_name) |
---|
612 | | - print datetime.datetime.today(), "Adding primary keys" |
---|
| 869 | + printdate("Adding primary keys") |
---|
613 | 870 | do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') |
---|
614 | 871 | do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)') |
---|
615 | 872 | do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)') |
---|
.. | .. |
---|
623 | 880 | do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)') |
---|
624 | 881 | if perf_db_export_calls: |
---|
625 | 882 | do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') |
---|
| 883 | + do_query(query, 'ALTER TABLE ptwrite ADD PRIMARY KEY (id)') |
---|
| 884 | + do_query(query, 'ALTER TABLE cbr ADD PRIMARY KEY (id)') |
---|
| 885 | + do_query(query, 'ALTER TABLE mwait ADD PRIMARY KEY (id)') |
---|
| 886 | + do_query(query, 'ALTER TABLE pwre ADD PRIMARY KEY (id)') |
---|
| 887 | + do_query(query, 'ALTER TABLE exstop ADD PRIMARY KEY (id)') |
---|
| 888 | + do_query(query, 'ALTER TABLE pwrx ADD PRIMARY KEY (id)') |
---|
| 889 | + do_query(query, 'ALTER TABLE context_switches ADD PRIMARY KEY (id)') |
---|
626 | 890 | |
---|
627 | | - print datetime.datetime.today(), "Adding foreign keys" |
---|
| 891 | + printdate("Adding foreign keys") |
---|
628 | 892 | do_query(query, 'ALTER TABLE threads ' |
---|
629 | 893 | 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' |
---|
630 | 894 | 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)') |
---|
| 895 | + do_query(query, 'ALTER TABLE comms ' |
---|
| 896 | + 'ADD CONSTRAINT threadfk FOREIGN KEY (c_thread_id) REFERENCES threads (id)') |
---|
631 | 897 | do_query(query, 'ALTER TABLE comm_threads ' |
---|
632 | 898 | 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),' |
---|
633 | 899 | 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id)') |
---|
.. | .. |
---|
657 | 923 | 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' |
---|
658 | 924 | 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') |
---|
659 | 925 | do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') |
---|
| 926 | + do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') |
---|
| 927 | + do_query(query, 'ALTER TABLE comms ADD has_calls boolean') |
---|
| 928 | + do_query(query, 'UPDATE comms SET has_calls = TRUE WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)') |
---|
| 929 | + do_query(query, 'ALTER TABLE ptwrite ' |
---|
| 930 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 931 | + do_query(query, 'ALTER TABLE cbr ' |
---|
| 932 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 933 | + do_query(query, 'ALTER TABLE mwait ' |
---|
| 934 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 935 | + do_query(query, 'ALTER TABLE pwre ' |
---|
| 936 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 937 | + do_query(query, 'ALTER TABLE exstop ' |
---|
| 938 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 939 | + do_query(query, 'ALTER TABLE pwrx ' |
---|
| 940 | + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') |
---|
| 941 | + do_query(query, 'ALTER TABLE context_switches ' |
---|
| 942 | + 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' |
---|
| 943 | + 'ADD CONSTRAINT toutfk FOREIGN KEY (thread_out_id) REFERENCES threads (id),' |
---|
| 944 | + 'ADD CONSTRAINT tinfk FOREIGN KEY (thread_in_id) REFERENCES threads (id),' |
---|
| 945 | + 'ADD CONSTRAINT coutfk FOREIGN KEY (comm_out_id) REFERENCES comms (id),' |
---|
| 946 | + 'ADD CONSTRAINT cinfk FOREIGN KEY (comm_in_id) REFERENCES comms (id)') |
---|
| 947 | + |
---|
| 948 | + printdate("Dropping unused tables") |
---|
| 949 | + if is_table_empty("ptwrite"): |
---|
| 950 | + drop("ptwrite") |
---|
| 951 | + if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"): |
---|
| 952 | + do_query(query, 'DROP VIEW power_events_view'); |
---|
| 953 | + drop("mwait") |
---|
| 954 | + drop("pwre") |
---|
| 955 | + drop("exstop") |
---|
| 956 | + drop("pwrx") |
---|
| 957 | + if is_table_empty("cbr"): |
---|
| 958 | + drop("cbr") |
---|
| 959 | + if is_table_empty("context_switches"): |
---|
| 960 | + drop("context_switches") |
---|
660 | 961 | |
---|
661 | 962 | if (unhandled_count): |
---|
662 | | - print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" |
---|
663 | | - print datetime.datetime.today(), "Done" |
---|
| 963 | + printdate("Warning: ", unhandled_count, " unhandled events") |
---|
| 964 | + printdate("Done") |
---|
664 | 965 | |
---|
665 | 966 | def trace_unhandled(event_name, context, event_fields_dict): |
---|
666 | 967 | global unhandled_count |
---|
.. | .. |
---|
670 | 971 | pass |
---|
671 | 972 | |
---|
672 | 973 | def evsel_table(evsel_id, evsel_name, *x): |
---|
| 974 | + evsel_name = toserverstr(evsel_name) |
---|
673 | 975 | n = len(evsel_name) |
---|
674 | 976 | fmt = "!hiqi" + str(n) + "s" |
---|
675 | 977 | value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name) |
---|
676 | 978 | evsel_file.write(value) |
---|
677 | 979 | |
---|
678 | 980 | def machine_table(machine_id, pid, root_dir, *x): |
---|
| 981 | + root_dir = toserverstr(root_dir) |
---|
679 | 982 | n = len(root_dir) |
---|
680 | 983 | fmt = "!hiqiii" + str(n) + "s" |
---|
681 | 984 | value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir) |
---|
.. | .. |
---|
685 | 988 | value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid) |
---|
686 | 989 | thread_file.write(value) |
---|
687 | 990 | |
---|
688 | | -def comm_table(comm_id, comm_str, *x): |
---|
| 991 | +def comm_table(comm_id, comm_str, thread_id, time, exec_flag, *x): |
---|
| 992 | + comm_str = toserverstr(comm_str) |
---|
689 | 993 | n = len(comm_str) |
---|
690 | | - fmt = "!hiqi" + str(n) + "s" |
---|
691 | | - value = struct.pack(fmt, 2, 8, comm_id, n, comm_str) |
---|
| 994 | + fmt = "!hiqi" + str(n) + "s" + "iqiqiB" |
---|
| 995 | + value = struct.pack(fmt, 5, 8, comm_id, n, comm_str, 8, thread_id, 8, time, 1, exec_flag) |
---|
692 | 996 | comm_file.write(value) |
---|
693 | 997 | |
---|
694 | 998 | def comm_thread_table(comm_thread_id, comm_id, thread_id, *x): |
---|
.. | .. |
---|
697 | 1001 | comm_thread_file.write(value) |
---|
698 | 1002 | |
---|
699 | 1003 | def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x): |
---|
| 1004 | + short_name = toserverstr(short_name) |
---|
| 1005 | + long_name = toserverstr(long_name) |
---|
| 1006 | + build_id = toserverstr(build_id) |
---|
700 | 1007 | n1 = len(short_name) |
---|
701 | 1008 | n2 = len(long_name) |
---|
702 | 1009 | n3 = len(build_id) |
---|
.. | .. |
---|
705 | 1012 | dso_file.write(value) |
---|
706 | 1013 | |
---|
707 | 1014 | def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x): |
---|
| 1015 | + symbol_name = toserverstr(symbol_name) |
---|
708 | 1016 | n = len(symbol_name) |
---|
709 | 1017 | fmt = "!hiqiqiqiqiii" + str(n) + "s" |
---|
710 | 1018 | value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name) |
---|
711 | 1019 | symbol_file.write(value) |
---|
712 | 1020 | |
---|
713 | 1021 | def branch_type_table(branch_type, name, *x): |
---|
| 1022 | + name = toserverstr(name) |
---|
714 | 1023 | n = len(name) |
---|
715 | 1024 | fmt = "!hiii" + str(n) + "s" |
---|
716 | 1025 | value = struct.pack(fmt, 2, 4, branch_type, n, name) |
---|
717 | 1026 | branch_type_file.write(value) |
---|
718 | 1027 | |
---|
719 | | -def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, call_path_id, *x): |
---|
| 1028 | +def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, call_path_id, insn_cnt, cyc_cnt, *x): |
---|
720 | 1029 | if branches: |
---|
721 | | - value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiBiq", 18, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx, 8, call_path_id) |
---|
| 1030 | + value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiBiqiqiq", 20, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx, 8, call_path_id, 8, insn_cnt, 8, cyc_cnt) |
---|
722 | 1031 | else: |
---|
723 | | - value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiBiq", 22, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx, 8, call_path_id) |
---|
| 1032 | + value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiBiqiqiq", 24, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx, 8, call_path_id, 8, insn_cnt, 8, cyc_cnt) |
---|
724 | 1033 | sample_file.write(value) |
---|
725 | 1034 | |
---|
726 | 1035 | def call_path_table(cp_id, parent_id, symbol_id, ip, *x): |
---|
.. | .. |
---|
728 | 1037 | value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) |
---|
729 | 1038 | call_path_file.write(value) |
---|
730 | 1039 | |
---|
731 | | -def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): |
---|
732 | | - fmt = "!hiqiqiqiqiqiqiqiqiqiqii" |
---|
733 | | - value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) |
---|
| 1040 | +def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, insn_cnt, cyc_cnt, *x): |
---|
| 1041 | + fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiqiqiq" |
---|
| 1042 | + value = struct.pack(fmt, 14, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id, 8, insn_cnt, 8, cyc_cnt) |
---|
734 | 1043 | call_file.write(value) |
---|
| 1044 | + |
---|
| 1045 | +def ptwrite(id, raw_buf): |
---|
| 1046 | + data = struct.unpack_from("<IQ", raw_buf) |
---|
| 1047 | + flags = data[0] |
---|
| 1048 | + payload = data[1] |
---|
| 1049 | + exact_ip = flags & 1 |
---|
| 1050 | + value = struct.pack("!hiqiqiB", 3, 8, id, 8, payload, 1, exact_ip) |
---|
| 1051 | + ptwrite_file.write(value) |
---|
| 1052 | + |
---|
| 1053 | +def cbr(id, raw_buf): |
---|
| 1054 | + data = struct.unpack_from("<BBBBII", raw_buf) |
---|
| 1055 | + cbr = data[0] |
---|
| 1056 | + MHz = (data[4] + 500) / 1000 |
---|
| 1057 | + percent = ((cbr * 1000 / data[2]) + 5) / 10 |
---|
| 1058 | + value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, int(MHz), 4, int(percent)) |
---|
| 1059 | + cbr_file.write(value) |
---|
| 1060 | + |
---|
| 1061 | +def mwait(id, raw_buf): |
---|
| 1062 | + data = struct.unpack_from("<IQ", raw_buf) |
---|
| 1063 | + payload = data[1] |
---|
| 1064 | + hints = payload & 0xff |
---|
| 1065 | + extensions = (payload >> 32) & 0x3 |
---|
| 1066 | + value = struct.pack("!hiqiiii", 3, 8, id, 4, hints, 4, extensions) |
---|
| 1067 | + mwait_file.write(value) |
---|
| 1068 | + |
---|
| 1069 | +def pwre(id, raw_buf): |
---|
| 1070 | + data = struct.unpack_from("<IQ", raw_buf) |
---|
| 1071 | + payload = data[1] |
---|
| 1072 | + hw = (payload >> 7) & 1 |
---|
| 1073 | + cstate = (payload >> 12) & 0xf |
---|
| 1074 | + subcstate = (payload >> 8) & 0xf |
---|
| 1075 | + value = struct.pack("!hiqiiiiiB", 4, 8, id, 4, cstate, 4, subcstate, 1, hw) |
---|
| 1076 | + pwre_file.write(value) |
---|
| 1077 | + |
---|
| 1078 | +def exstop(id, raw_buf): |
---|
| 1079 | + data = struct.unpack_from("<I", raw_buf) |
---|
| 1080 | + flags = data[0] |
---|
| 1081 | + exact_ip = flags & 1 |
---|
| 1082 | + value = struct.pack("!hiqiB", 2, 8, id, 1, exact_ip) |
---|
| 1083 | + exstop_file.write(value) |
---|
| 1084 | + |
---|
| 1085 | +def pwrx(id, raw_buf): |
---|
| 1086 | + data = struct.unpack_from("<IQ", raw_buf) |
---|
| 1087 | + payload = data[1] |
---|
| 1088 | + deepest_cstate = payload & 0xf |
---|
| 1089 | + last_cstate = (payload >> 4) & 0xf |
---|
| 1090 | + wake_reason = (payload >> 8) & 0xf |
---|
| 1091 | + value = struct.pack("!hiqiiiiii", 4, 8, id, 4, deepest_cstate, 4, last_cstate, 4, wake_reason) |
---|
| 1092 | + pwrx_file.write(value) |
---|
| 1093 | + |
---|
| 1094 | +def synth_data(id, config, raw_buf, *x): |
---|
| 1095 | + if config == 0: |
---|
| 1096 | + ptwrite(id, raw_buf) |
---|
| 1097 | + elif config == 1: |
---|
| 1098 | + mwait(id, raw_buf) |
---|
| 1099 | + elif config == 2: |
---|
| 1100 | + pwre(id, raw_buf) |
---|
| 1101 | + elif config == 3: |
---|
| 1102 | + exstop(id, raw_buf) |
---|
| 1103 | + elif config == 4: |
---|
| 1104 | + pwrx(id, raw_buf) |
---|
| 1105 | + elif config == 5: |
---|
| 1106 | + cbr(id, raw_buf) |
---|
| 1107 | + |
---|
| 1108 | +def context_switch_table(id, machine_id, time, cpu, thread_out_id, comm_out_id, thread_in_id, comm_in_id, flags, *x): |
---|
| 1109 | + fmt = "!hiqiqiqiiiqiqiqiqii" |
---|
| 1110 | + value = struct.pack(fmt, 9, 8, id, 8, machine_id, 8, time, 4, cpu, 8, thread_out_id, 8, comm_out_id, 8, thread_in_id, 8, comm_in_id, 4, flags) |
---|
| 1111 | + context_switches_file.write(value) |
---|