Re: [PATCH v2] perf record: encode -k clockid frequency into Perf trace
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
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
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
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
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
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
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
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", +