perf data: Add JSON export
authorNicholas Fraser <nfraser@codeweavers.com>
Mon, 26 Apr 2021 14:47:16 +0000 (10:47 -0400)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 29 Apr 2021 13:30:58 +0000 (10:30 -0300)
commitd0713d4ca3e94827de77f8758e3e8045a0d85215
tree547d06b3ca85e9090499cf00e238b2fe785d3ecd
parent5508c9dae2a4a111acc7472900164f556ae75346
perf data: Add JSON export

This adds a feature to export perf data to JSON.

The resolved symbols are exported into the JSON so that external tools
don't need to load the dsos themselves (or even have access to them at
all.) This makes it easy to load and analyze perf data with standalone
tools where direct perf or libbabeltrace integration is impractical.

The exporter uses a minimal inline JSON encoding without any external
dependencies. Currently it only outputs some headers and sample metadata
but it's easily extensible.

Use it like this:

  $ perf data convert --to-json out.json

Committer notes:

Fixup a __printf() bug that broke the build:

  util/data-convert-json.c:103:11: error: expected ‘)’ before numeric constant
    103 | __(printf, 5, 6)
        |           ^~
        |           )
  util/data-convert-json.c: In function ‘output_sample_callchain_entry’:
  util/data-convert-json.c:124:2: error: implicit declaration of function ‘output_json_key_format’; did you mean ‘output_json_format’? [-Werror=implicit-function-declaration]
    124 |  output_json_key_format(out, false, 5, "ip", "\"0x%" PRIx64 "\"", ip);
        |  ^~~~~~~~~~~~~~~~~~~~~~
        |  output_json_format

Also had to add this patch to fix errors reported by various versions of
clang:

  -       if (al && al->sym && al->sym->name && strlen(al->sym->name) > 0) {
  +       if (al && al->sym && al->sym->namelen) {

al->sym->name is a zero sized array, to avoid one extra alloc in the
symbol__new() constructor, sym->namelen carries its strlen.

Committer testing:

  $ ls -la out.json
  ls: cannot access 'out.json': No such file or directory
  $ perf record sleep 0.1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.001 MB perf.data (8 samples) ]
  $ perf report --stats | grep -w SAMPLE
            SAMPLE events:          8
  $ perf data convert --to-json out.json
  [ perf data convert: Converted 'perf.data' into JSON data 'out.json' ]
  [ perf data convert: Converted and wrote 0.002 MB (8 samples) ]
  $ ls -la out.json
  -rw-rw-r--. 1 acme acme 2017 Apr 26 17:29 out.json
  $ cat out.json
  {
   "linux-perf-json-version": 1,
   "headers": {
   "header-version": 1,
   "captured-on": "2021-04-26T20:28:57Z",
   "data-offset": 432,
   "data-size": 1016,
   "feat-offset": 1448,
   "hostname": "five",
   "os-release": "5.11.14-200.fc33.x86_64",
   "arch": "x86_64",
   "cpu-desc": "AMD Ryzen 9 3900X 12-Core Processor",
   "cpuid": "AuthenticAMD,23,113,0",
   "nrcpus-online": 24,
   "nrcpus-avail": 24,
   "perf-version": "5.12.gee134f3189bd",
   "cmdline": [
   "/home/acme/bin/perf",
   "record",
   "sleep",
   "0.1"
   ]
   },
   "samples": [
   {
   "timestamp": 170517539043684,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0xffffffffa6268827"
   }
   ]
   },
   {
   "timestamp": 170517539048443,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0xffffffffa661359d"
   }
   ]
   },
   {
   "timestamp": 170517539051018,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0xffffffffa6311e18"
   }
   ]
   },
   {
   "timestamp": 170517539053652,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0x7fdb77b4812b",
   "symbol": "_dl_start",
   "dso": "ld-2.32.so"
   }
   ]
   },
   {
   "timestamp": 170517539055306,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0xffffffffa6269286"
   }
   ]
   },
   {
   "timestamp": 170517539057590,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0xffffffffa62abd8b"
   }
   ]
   },
   {
   "timestamp": 170517539067559,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0x7fdb77b5e9e9",
   "symbol": "__GI___tunables_init",
   "dso": "ld-2.32.so"
   }
   ]
   },
   {
   "timestamp": 170517539282452,
   "pid": 375844,
   "tid": 375844,
   "comm": "sleep",
   "callchain": [
   {
   "ip": "0x7fdb779978d2",
   "symbol": "getenv",
   "dso": "libc-2.32.so"
   }
   ]
   }
   ]
  }
  $

Signed-off-by: Nicholas Fraser <nfraser@codeweavers.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Changbin Du <changbin.du@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jin Yao <yao.jin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tan Xiaojun <tanxiaojun@huawei.com>
Cc: Ulrich Czekalla <uczekalla@codeweavers.com>
Link: http://lore.kernel.org/lkml/3884969f-804d-2f53-c648-e2b0bd85edff@codeweavers.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/Documentation/perf-data.txt
tools/perf/builtin-data.c
tools/perf/util/Build
tools/perf/util/data-convert-bt.c
tools/perf/util/data-convert-bt.h [deleted file]
tools/perf/util/data-convert-json.c [new file with mode: 0644]
tools/perf/util/data-convert.h