Re: [PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Alexey Budankov
Hi,

On 03.10.2018 16:39, Jiri Olsa wrote:
> On Wed, Oct 03, 2018 at 10:01:56AM +0300, Alexey Budankov wrote:

>> +if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
>> +session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
>> +else
>> +perf_header__clear_feat(>header, HEADER_CLOCKID);
>> +
> 
> could you please keep only bits setting in record__init_features
> and move the header.env.clockid_res_ns assignment out of it?

Ok. Accepted.

> 

>> +static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
>> +{
>> +struct timespec res;
>> +
>> +*res_ns = 0;
>> +if (!clock_getres(clk_id, ))
>> +*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
> 
> hum, if this one fails (which I guess is unlikely) we should tell
> and probably even quit

Makes sense. Please stay tuned for v3.

Thanks,
Alexey


Re: [PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Alexey Budankov
Hi,

On 03.10.2018 16:39, Jiri Olsa wrote:
> On Wed, Oct 03, 2018 at 10:01:56AM +0300, Alexey Budankov wrote:

>> +if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
>> +session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
>> +else
>> +perf_header__clear_feat(>header, HEADER_CLOCKID);
>> +
> 
> could you please keep only bits setting in record__init_features
> and move the header.env.clockid_res_ns assignment out of it?

Ok. Accepted.

> 

>> +static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
>> +{
>> +struct timespec res;
>> +
>> +*res_ns = 0;
>> +if (!clock_getres(clk_id, ))
>> +*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
> 
> hum, if this one fails (which I guess is unlikely) we should tell
> and probably even quit

Makes sense. Please stay tuned for v3.

Thanks,
Alexey


Re: [PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Jiri Olsa
On Wed, Oct 03, 2018 at 10:01:56AM +0300, Alexey Budankov wrote:
> 
> Store -k clockid frequency into Perf trace to enable timestamps 
> derived metrics conversion into wall clock time on reporting stage.
> 
> Below is the example of perf report output:
> 
> tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
> ...
> [ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]
> 
> tools/perf/perf report --header
> # 
> ...
> # event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
> 4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
> comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, 
> sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 
> 1, clockid = 4
> ...
> # clockid frequency: 1000 MHz
> ...
> # 
> 
> Signed-off-by: Alexey Budankov 
> ---
> Changes in v2:
>  - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
> get_clockid_res()
>  - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
>  - moved MHz conversion into print_clockid() and shortened write_clockid()
> ---
>  tools/perf/builtin-record.c | 21 +++--
>  tools/perf/perf.h   |  1 +
>  tools/perf/util/env.h   |  1 +
>  tools/perf/util/header.c| 27 +++
>  tools/perf/util/header.h|  1 +
>  5 files changed, 49 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 0980dfe3396b..127dc7432394 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
>   if (!rec->opts.full_auxtrace)
>   perf_header__clear_feat(>header, HEADER_AUXTRACE);
>  
> + if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
> + session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
> + else
> + perf_header__clear_feat(>header, HEADER_CLOCKID);
> +

could you please keep only bits setting in record__init_features
and move the header.env.clockid_res_ns assignment out of it?

sry for not catching this in the first version

>   perf_header__clear_feat(>header, HEADER_STAT);
>  }
>  
> @@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
>   CLOCKID_END,
>  };
>  
> +static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
> +{
> + struct timespec res;
> +
> + *res_ns = 0;
> + if (!clock_getres(clk_id, ))
> + *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;

hum, if this one fails (which I guess is unlikely) we should tell
and probably even quit

thanks,
jirka


Re: [PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Jiri Olsa
On Wed, Oct 03, 2018 at 10:01:56AM +0300, Alexey Budankov wrote:
> 
> Store -k clockid frequency into Perf trace to enable timestamps 
> derived metrics conversion into wall clock time on reporting stage.
> 
> Below is the example of perf report output:
> 
> tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
> ...
> [ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]
> 
> tools/perf/perf report --header
> # 
> ...
> # event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
> 4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
> comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, 
> sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 
> 1, clockid = 4
> ...
> # clockid frequency: 1000 MHz
> ...
> # 
> 
> Signed-off-by: Alexey Budankov 
> ---
> Changes in v2:
>  - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
> get_clockid_res()
>  - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
>  - moved MHz conversion into print_clockid() and shortened write_clockid()
> ---
>  tools/perf/builtin-record.c | 21 +++--
>  tools/perf/perf.h   |  1 +
>  tools/perf/util/env.h   |  1 +
>  tools/perf/util/header.c| 27 +++
>  tools/perf/util/header.h|  1 +
>  5 files changed, 49 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 0980dfe3396b..127dc7432394 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
>   if (!rec->opts.full_auxtrace)
>   perf_header__clear_feat(>header, HEADER_AUXTRACE);
>  
> + if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
> + session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
> + else
> + perf_header__clear_feat(>header, HEADER_CLOCKID);
> +

could you please keep only bits setting in record__init_features
and move the header.env.clockid_res_ns assignment out of it?

sry for not catching this in the first version

>   perf_header__clear_feat(>header, HEADER_STAT);
>  }
>  
> @@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
>   CLOCKID_END,
>  };
>  
> +static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
> +{
> + struct timespec res;
> +
> + *res_ns = 0;
> + if (!clock_getres(clk_id, ))
> + *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;

hum, if this one fails (which I guess is unlikely) we should tell
and probably even quit

thanks,
jirka


[PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Alexey Budankov


Store -k clockid frequency into Perf trace to enable timestamps 
derived metrics conversion into wall clock time on reporting stage.

Below is the example of perf report output:

tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
...
[ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]

tools/perf/perf report --header
# 
...
# event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all 
= 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 1, clockid = 4
...
# clockid frequency: 1000 MHz
...
# 

Signed-off-by: Alexey Budankov 
---
Changes in v2:
 - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
get_clockid_res()
 - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
 - moved MHz conversion into print_clockid() and shortened write_clockid()
---
 tools/perf/builtin-record.c | 21 +++--
 tools/perf/perf.h   |  1 +
 tools/perf/util/env.h   |  1 +
 tools/perf/util/header.c| 27 +++
 tools/perf/util/header.h|  1 +
 5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0980dfe3396b..127dc7432394 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace)
perf_header__clear_feat(>header, HEADER_AUXTRACE);
 
+   if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
+   session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
+   else
+   perf_header__clear_feat(>header, HEADER_CLOCKID);
+
perf_header__clear_feat(>header, HEADER_STAT);
 }
 
@@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
CLOCKID_END,
 };
 
+static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
+{
+   struct timespec res;
+
+   *res_ns = 0;
+   if (!clock_getres(clk_id, ))
+   *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
+
+   return 0;
+}
+
 static int parse_clockid(const struct option *opt, const char *str, int unset)
 {
struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1360,7 +1376,7 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
 
/* if its a number, we're done */
if (sscanf(str, "%d", >clockid) == 1)
-   return 0;
+   return get_clockid_res(opts->clockid, >clockid_res_ns);
 
/* allow a "CLOCK_" prefix to the name */
if (!strncasecmp(str, "CLOCK_", 6))
@@ -1369,7 +1385,8 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
for (cm = clockids; cm->name; cm++) {
if (!strcasecmp(str, cm->name)) {
opts->clockid = cm->clockid;
-   return 0;
+   return get_clockid_res(opts->clockid,
+  >clockid_res_ns);
}
}
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..981db3c2ed60 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
unsigned initial_delay;
bool use_clockid;
clockid_tclockid;
+   size_t   clockid_res_ns;
unsigned int proc_map_timeout;
 };
 
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..b167a54d635f 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
struct numa_node*numa_nodes;
struct memory_node  *memory_nodes;
unsigned long long   memory_bsize;
+   size_t   clockid_res_ns;
 };
 
 extern struct perf_env perf_env;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ec1d9bc2d63..4ce5339158f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
return err;
 }
 
+static int write_clockid(struct feat_fd *ff,
+struct perf_evlist *evlist __maybe_unused)
+{
+   return do_write(ff, >ph->env.clockid_res_ns,
+   sizeof(ff->ph->env.clockid_res_ns));
+}
+
 static int cpu_cache_level__sort(const void *a, const void *b)
 {
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE 
*fp)
fprintf(fp, "# Core ID and Socket ID information is not 
available\n");
 }
 
+static void print_clockid(struct feat_fd *ff, FILE *fp)
+{
+   fprintf(fp, "# clockid frequency: %ld MHz\n",
+   

[PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-10-03 Thread Alexey Budankov


Store -k clockid frequency into Perf trace to enable timestamps 
derived metrics conversion into wall clock time on reporting stage.

Below is the example of perf report output:

tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
...
[ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]

tools/perf/perf report --header
# 
...
# event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all 
= 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 1, clockid = 4
...
# clockid frequency: 1000 MHz
...
# 

Signed-off-by: Alexey Budankov 
---
Changes in v2:
 - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
get_clockid_res()
 - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
 - moved MHz conversion into print_clockid() and shortened write_clockid()
---
 tools/perf/builtin-record.c | 21 +++--
 tools/perf/perf.h   |  1 +
 tools/perf/util/env.h   |  1 +
 tools/perf/util/header.c| 27 +++
 tools/perf/util/header.h|  1 +
 5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0980dfe3396b..127dc7432394 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace)
perf_header__clear_feat(>header, HEADER_AUXTRACE);
 
+   if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
+   session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
+   else
+   perf_header__clear_feat(>header, HEADER_CLOCKID);
+
perf_header__clear_feat(>header, HEADER_STAT);
 }
 
@@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
CLOCKID_END,
 };
 
+static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
+{
+   struct timespec res;
+
+   *res_ns = 0;
+   if (!clock_getres(clk_id, ))
+   *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
+
+   return 0;
+}
+
 static int parse_clockid(const struct option *opt, const char *str, int unset)
 {
struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1360,7 +1376,7 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
 
/* if its a number, we're done */
if (sscanf(str, "%d", >clockid) == 1)
-   return 0;
+   return get_clockid_res(opts->clockid, >clockid_res_ns);
 
/* allow a "CLOCK_" prefix to the name */
if (!strncasecmp(str, "CLOCK_", 6))
@@ -1369,7 +1385,8 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
for (cm = clockids; cm->name; cm++) {
if (!strcasecmp(str, cm->name)) {
opts->clockid = cm->clockid;
-   return 0;
+   return get_clockid_res(opts->clockid,
+  >clockid_res_ns);
}
}
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..981db3c2ed60 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
unsigned initial_delay;
bool use_clockid;
clockid_tclockid;
+   size_t   clockid_res_ns;
unsigned int proc_map_timeout;
 };
 
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..b167a54d635f 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
struct numa_node*numa_nodes;
struct memory_node  *memory_nodes;
unsigned long long   memory_bsize;
+   size_t   clockid_res_ns;
 };
 
 extern struct perf_env perf_env;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ec1d9bc2d63..4ce5339158f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
return err;
 }
 
+static int write_clockid(struct feat_fd *ff,
+struct perf_evlist *evlist __maybe_unused)
+{
+   return do_write(ff, >ph->env.clockid_res_ns,
+   sizeof(ff->ph->env.clockid_res_ns));
+}
+
 static int cpu_cache_level__sort(const void *a, const void *b)
 {
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE 
*fp)
fprintf(fp, "# Core ID and Socket ID information is not 
available\n");
 }
 
+static void print_clockid(struct feat_fd *ff, FILE *fp)
+{
+   fprintf(fp, "# clockid frequency: %ld MHz\n",
+   

[PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-09-28 Thread Alexey Budankov


Store -k clockid frequency into Perf trace to enable timestamps 
derived metrics conversion into wall clock time on reporting stage.

Below is the example of perf report output:

tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
...
[ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]

tools/perf/perf report --header
# 
...
# event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all 
= 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 1, clockid = 4
...
# clockid frequency: 1000 MHz
...
# 

Signed-off-by: Alexey Budankov 
---
Changes in v2:
 - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
get_clockid_res()
 - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
 - moved MHz conversion into print_clockid() and shortened write_clockid()
---
 tools/perf/builtin-record.c | 21 +++--
 tools/perf/perf.h   |  1 +
 tools/perf/util/env.h   |  1 +
 tools/perf/util/header.c| 27 +++
 tools/perf/util/header.h|  1 +
 5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0980dfe3396b..127dc7432394 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace)
perf_header__clear_feat(>header, HEADER_AUXTRACE);
 
+   if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
+   session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
+   else
+   perf_header__clear_feat(>header, HEADER_CLOCKID);
+
perf_header__clear_feat(>header, HEADER_STAT);
 }
 
@@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
CLOCKID_END,
 };
 
+static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
+{
+   struct timespec res;
+
+   *res_ns = 0;
+   if (!clock_getres(clk_id, ))
+   *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
+
+   return 0;
+}
+
 static int parse_clockid(const struct option *opt, const char *str, int unset)
 {
struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1360,7 +1376,7 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
 
/* if its a number, we're done */
if (sscanf(str, "%d", >clockid) == 1)
-   return 0;
+   return get_clockid_res(opts->clockid, >clockid_res_ns);
 
/* allow a "CLOCK_" prefix to the name */
if (!strncasecmp(str, "CLOCK_", 6))
@@ -1369,7 +1385,8 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
for (cm = clockids; cm->name; cm++) {
if (!strcasecmp(str, cm->name)) {
opts->clockid = cm->clockid;
-   return 0;
+   return get_clockid_res(opts->clockid,
+  >clockid_res_ns);
}
}
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..981db3c2ed60 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
unsigned initial_delay;
bool use_clockid;
clockid_tclockid;
+   size_t   clockid_res_ns;
unsigned int proc_map_timeout;
 };
 
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..b167a54d635f 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
struct numa_node*numa_nodes;
struct memory_node  *memory_nodes;
unsigned long long   memory_bsize;
+   size_t   clockid_res_ns;
 };
 
 extern struct perf_env perf_env;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ec1d9bc2d63..4ce5339158f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
return err;
 }
 
+static int write_clockid(struct feat_fd *ff,
+struct perf_evlist *evlist __maybe_unused)
+{
+   return do_write(ff, >ph->env.clockid_res_ns,
+   sizeof(ff->ph->env.clockid_res_ns));
+}
+
 static int cpu_cache_level__sort(const void *a, const void *b)
 {
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE 
*fp)
fprintf(fp, "# Core ID and Socket ID information is not 
available\n");
 }
 
+static void print_clockid(struct feat_fd *ff, FILE *fp)
+{
+   fprintf(fp, "# clockid frequency: %ld MHz\n",
+   

[PATCH v2] perf record: encode -k clockid frequency into Perf trace

2018-09-28 Thread Alexey Budankov


Store -k clockid frequency into Perf trace to enable timestamps 
derived metrics conversion into wall clock time on reporting stage.

Below is the example of perf report output:

tools/perf/perf record -k raw -- ../../matrix/linux/matrix.gcc
...
[ perf record: Captured and wrote 31.222 MB perf.data (818054 samples) ]

tools/perf/perf report --header
# 
...
# event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 
4000, sample_type = IP|TID|TIME|PERIOD, disabled = 1, inherit = 1, mmap = 1, 
comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all 
= 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, use_clockid = 1, clockid = 4
...
# clockid frequency: 1000 MHz
...
# 

Signed-off-by: Alexey Budankov 
---
Changes in v2:
 - renamed clockid_freq to clockid_res_ns and get_clockid_freq() to 
get_clockid_res()
 - avoided redundant define of NSEC_IN_SEC, reused linux/time64.h:NSEC_PER_SEC
 - moved MHz conversion into print_clockid() and shortened write_clockid()
---
 tools/perf/builtin-record.c | 21 +++--
 tools/perf/perf.h   |  1 +
 tools/perf/util/env.h   |  1 +
 tools/perf/util/header.c| 27 +++
 tools/perf/util/header.h|  1 +
 5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0980dfe3396b..127dc7432394 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -592,6 +592,11 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace)
perf_header__clear_feat(>header, HEADER_AUXTRACE);
 
+   if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
+   session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
+   else
+   perf_header__clear_feat(>header, HEADER_CLOCKID);
+
perf_header__clear_feat(>header, HEADER_STAT);
 }
 
@@ -1337,6 +1342,17 @@ static const struct clockid_map clockids[] = {
CLOCKID_END,
 };
 
+static int get_clockid_res(clockid_t clk_id, size_t *res_ns)
+{
+   struct timespec res;
+
+   *res_ns = 0;
+   if (!clock_getres(clk_id, ))
+   *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
+
+   return 0;
+}
+
 static int parse_clockid(const struct option *opt, const char *str, int unset)
 {
struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1360,7 +1376,7 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
 
/* if its a number, we're done */
if (sscanf(str, "%d", >clockid) == 1)
-   return 0;
+   return get_clockid_res(opts->clockid, >clockid_res_ns);
 
/* allow a "CLOCK_" prefix to the name */
if (!strncasecmp(str, "CLOCK_", 6))
@@ -1369,7 +1385,8 @@ static int parse_clockid(const struct option *opt, const 
char *str, int unset)
for (cm = clockids; cm->name; cm++) {
if (!strcasecmp(str, cm->name)) {
opts->clockid = cm->clockid;
-   return 0;
+   return get_clockid_res(opts->clockid,
+  >clockid_res_ns);
}
}
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..981db3c2ed60 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
unsigned initial_delay;
bool use_clockid;
clockid_tclockid;
+   size_t   clockid_res_ns;
unsigned int proc_map_timeout;
 };
 
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..b167a54d635f 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
struct numa_node*numa_nodes;
struct memory_node  *memory_nodes;
unsigned long long   memory_bsize;
+   size_t   clockid_res_ns;
 };
 
 extern struct perf_env perf_env;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ec1d9bc2d63..4ce5339158f7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
return err;
 }
 
+static int write_clockid(struct feat_fd *ff,
+struct perf_evlist *evlist __maybe_unused)
+{
+   return do_write(ff, >ph->env.clockid_res_ns,
+   sizeof(ff->ph->env.clockid_res_ns));
+}
+
 static int cpu_cache_level__sort(const void *a, const void *b)
 {
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE 
*fp)
fprintf(fp, "# Core ID and Socket ID information is not 
available\n");
 }
 
+static void print_clockid(struct feat_fd *ff, FILE *fp)
+{
+   fprintf(fp, "# clockid frequency: %ld MHz\n",
+