Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf data: Add support to store time of day in CTF data conversion

Adad support to convert and store time of day in CTF data conversion for
'perf data convert' subcommand.

The perf.data used for conversion needs to have clock data information -
must be recorded with -k/--clockid option).

New --tod option is added to 'perf data convert' subcommand to convert
data with timestamps converted to wall clock time.

Record data with clockid set:

# perf record -k CLOCK_MONOTONIC kill
kill: not enough arguments
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.033 MB perf.data (8 samples) ]

Convert data with TOD timestamps:

# perf data convert --tod --to-ctf ./ctf
[ perf data convert: Converted 'perf.data' into CTF data './ctf' ]
[ perf data convert: Converted and wrote 0.000 MB (8 samples) ]

Display data in perf script:

# perf script -F+tod --ns
perf 262150 2020-07-13 18:38:50.097678523 153633.958246159: 1 cycles: ...
perf 262150 2020-07-13 18:38:50.097682941 153633.958250577: 1 cycles: ...
perf 262150 2020-07-13 18:38:50.097684997 153633.958252633: 7 cycles: ...
...

Display data in babeltrace:

# babeltrace --clock-date ./ctf
[2020-07-13 18:38:50.097678523] (+?.?????????) cycles: { cpu_id = 0 }, { perf_ip = 0xFFF ...
[2020-07-13 18:38:50.097682941] (+0.000004418) cycles: { cpu_id = 0 }, { perf_ip = 0xFFF ...
[2020-07-13 18:38:50.097684997] (+0.000002056) cycles: { cpu_id = 0 }, { perf_ip = 0xFFF ...
...

It's available only for recording with clockid specified, because it's
the only case where we can get reference time to wallclock time. It's
can't do that with perf clock yet.

Error is display if you want to use --tod on data without clockid
specified:

# perf data convert --tod --to-ctf ./ctf
Can't provide --tod time, missing clock data. Please record with -k/--clockid option.
Failed to setup CTF writer.
Error during conversion setup.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Geneviève Bastien <gbastien@versatic.net>
Cc: Ian Rogers <irogers@google.com>
Cc: Jeremie Galarneau <jgalar@efficios.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lore.kernel.org/lkml/20200805093444.314999-6-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
88371c58 9d88a1a1

+42 -20
+3
tools/perf/Documentation/perf-data.txt
··· 27 27 --to-ctf:: 28 28 Triggers the CTF conversion, specify the path of CTF data directory. 29 29 30 + --tod:: 31 + Convert time to wall clock time. 32 + 30 33 -i:: 31 34 Specify input perf data file path. 32 35
+1
tools/perf/builtin-data.c
··· 65 65 OPT_STRING('i', "input", &input_name, "file", "input file name"), 66 66 #ifdef HAVE_LIBBABELTRACE_SUPPORT 67 67 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), 68 + OPT_BOOLEAN(0, "tod", &opts.tod, "Convert time to wall clock time"), 68 69 #endif 69 70 OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"), 70 71 OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"),
+37 -20
tools/perf/util/data-convert-bt.c
··· 31 31 #include "config.h" 32 32 #include <linux/ctype.h> 33 33 #include <linux/err.h> 34 + #include <linux/time64.h> 35 + #include "util.h" 36 + #include "clockid.h" 34 37 35 38 #define pr_N(n, fmt, ...) \ 36 39 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) ··· 1384 1381 return 0; 1385 1382 } 1386 1383 1387 - static int ctf_writer__setup_clock(struct ctf_writer *cw) 1384 + static int ctf_writer__setup_clock(struct ctf_writer *cw, 1385 + struct perf_session *session, 1386 + bool tod) 1388 1387 { 1389 1388 struct bt_ctf_clock *clock = cw->clock; 1389 + const char *desc = "perf clock"; 1390 + int64_t offset = 0; 1390 1391 1391 - bt_ctf_clock_set_description(clock, "perf clock"); 1392 + if (tod) { 1393 + struct perf_env *env = &session->header.env; 1394 + 1395 + if (!env->clock.enabled) { 1396 + pr_err("Can't provide --tod time, missing clock data. " 1397 + "Please record with -k/--clockid option.\n"); 1398 + return -1; 1399 + } 1400 + 1401 + desc = clockid_name(env->clock.clockid); 1402 + offset = env->clock.tod_ns - env->clock.clockid_ns; 1403 + } 1392 1404 1393 1405 #define SET(__n, __v) \ 1394 1406 do { \ ··· 1412 1394 } while (0) 1413 1395 1414 1396 SET(frequency, 1000000000); 1415 - SET(offset_s, 0); 1416 - SET(offset, 0); 1397 + SET(offset, offset); 1398 + SET(description, desc); 1417 1399 SET(precision, 10); 1418 1400 SET(is_absolute, 0); 1419 1401 ··· 1499 1481 memset(cw, 0, sizeof(*cw)); 1500 1482 } 1501 1483 1502 - static int ctf_writer__init(struct ctf_writer *cw, const char *path) 1484 + static int ctf_writer__init(struct ctf_writer *cw, const char *path, 1485 + struct perf_session *session, bool tod) 1503 1486 { 1504 1487 struct bt_ctf_writer *writer; 1505 1488 struct bt_ctf_stream_class *stream_class; ··· 1524 1505 1525 1506 cw->clock = clock; 1526 1507 1527 - if (ctf_writer__setup_clock(cw)) { 1508 + if (ctf_writer__setup_clock(cw, session, tod)) { 1528 1509 pr("Failed to setup CTF clock.\n"); 1529 1510 goto err_cleanup; 1530 1511 } ··· 1632 1613 if (err) 1633 1614 return err; 1634 1615 1635 - /* CTF writer */ 1636 - if (ctf_writer__init(cw, path)) 1637 - return -1; 1638 - 1639 1616 err = -1; 1640 1617 /* perf.data session */ 1641 1618 session = perf_session__new(&data, 0, &c.tool); 1642 - if (IS_ERR(session)) { 1643 - err = PTR_ERR(session); 1644 - goto free_writer; 1645 - } 1619 + if (IS_ERR(session)) 1620 + return PTR_ERR(session); 1621 + 1622 + /* CTF writer */ 1623 + if (ctf_writer__init(cw, path, session, opts->tod)) 1624 + goto free_session; 1646 1625 1647 1626 if (c.queue_size) { 1648 1627 ordered_events__set_alloc_size(&session->ordered_events, ··· 1649 1632 1650 1633 /* CTF writer env/clock setup */ 1651 1634 if (ctf_writer__setup_env(cw, session)) 1652 - goto free_session; 1635 + goto free_writer; 1653 1636 1654 1637 /* CTF events setup */ 1655 1638 if (setup_events(cw, session)) 1656 - goto free_session; 1639 + goto free_writer; 1657 1640 1658 1641 if (opts->all && setup_non_sample_events(cw, session)) 1659 - goto free_session; 1642 + goto free_writer; 1660 1643 1661 1644 if (setup_streams(cw, session)) 1662 - goto free_session; 1645 + goto free_writer; 1663 1646 1664 1647 err = perf_session__process_events(session); 1665 1648 if (!err) ··· 1687 1670 1688 1671 return err; 1689 1672 1690 - free_session: 1691 - perf_session__delete(session); 1692 1673 free_writer: 1693 1674 ctf_writer__cleanup(cw); 1675 + free_session: 1676 + perf_session__delete(session); 1694 1677 pr_err("Error during conversion setup.\n"); 1695 1678 return err; 1696 1679 }
+1
tools/perf/util/data-convert.h
··· 5 5 struct perf_data_convert_opts { 6 6 bool force; 7 7 bool all; 8 + bool tod; 8 9 }; 9 10 10 11 #endif /* __DATA_CONVERT_H */