lkml.org 
[lkml]   [2022]   [Jul]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH v3 1/2] perf metrics: Add literal for system TSC frequency
From

Thanks Ian for working on the issue and coordinate the patches.

On 2022-07-15 6:35 p.m., Ian Rogers wrote:
> Such a literal is useful to calculate things like the average frequency
> [1]. The TSC frequency isn't exposed by sysfs although some experimental
> drivers look to add it [2]. This change computes the value using the
> frequency in /proc/cpuinfo which is accruate

%s/accruate/accurate/

> at least on Intel processors.

I googled the cpuinfo of other Archs, e.g., arm and s390. It looks like
only Intel display the TSC frequency in the "model name".

So it may be better to move it to X86 specific code, arch/x86/util/tsc.c

>
> [1] https://github.com/intel/perfmon-metrics/blob/5ad9ef7056f31075e8178b9f1fb732af183b2c8d/SKX/metrics/perf/skx_metric_perf.json#L11
> [2] https://github.com/trailofbits/tsc_freq_khz
>
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
> tools/perf/tests/expr.c | 15 +++++++++++++
> tools/perf/util/expr.c | 49 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 64 insertions(+)
>
> diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
> index 5c0032fe93ae..45afe4f24859 100644
> --- a/tools/perf/tests/expr.c
> +++ b/tools/perf/tests/expr.c
> @@ -1,8 +1,10 @@
> // SPDX-License-Identifier: GPL-2.0
> #include "util/debug.h"
> #include "util/expr.h"
> +#include "util/header.h"
> #include "util/smt.h"
> #include "tests.h"
> +#include <math.h>
> #include <stdlib.h>
> #include <string.h>
> #include <linux/zalloc.h>
> @@ -69,6 +71,11 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
> double val, num_cpus, num_cores, num_dies, num_packages;
> int ret;
> struct expr_parse_ctx *ctx;
> + bool is_intel = false;
> + char buf[128];
> +
> + if (!get_cpuid(buf, sizeof(buf)))
> + is_intel = strstr(buf, "Intel") != NULL;
>
> TEST_ASSERT_EQUAL("ids_union", test_ids_union(), 0);
>
> @@ -175,6 +182,14 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
> if (num_dies) // Some platforms do not have CPU die support, for example s390
> TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages);
>
> + if (is_intel) {
> + double system_tsc_freq;
> +
> + TEST_ASSERT_VAL("#system_tsc_freq", expr__parse(&system_tsc_freq, ctx,
> + "#system_tsc_freq") == 0);


I think we should use arch_get_tsc_freq() to replace here.
This belong to a separate patch.


Thanks,
Kan
> + TEST_ASSERT_VAL("!isnan(#system_tsc_freq)", !isnan(system_tsc_freq));
> + }
> +
> /*
> * Source count returns the number of events aggregating in a leader
> * event including the leader. Check parsing yields an id.
> diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
> index 675f318ce7c1..4c81533e4b43 100644
> --- a/tools/perf/util/expr.c
> +++ b/tools/perf/util/expr.c
> @@ -402,6 +402,50 @@ double expr_id_data__source_count(const struct expr_id_data *data)
> return data->val.source_count;
> }
>
> +/*
> + * Derive the TSC frequency in Hz from the /proc/cpuinfo, for example:
> + * ...
> + * model name : Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz
> + * ...
> + * will return 3000000000.
> + */
> +static double system_tsc_freq(void)
> +{
> + static double result;
> + static bool computed;
> + FILE *cpuinfo;
> + char *line = NULL;
> + size_t len = 0;
> +
> + if (computed)
> + return result;
> +
> + computed = true;
> + result = NAN;
> + cpuinfo = fopen("/proc/cpuinfo", "r");
> + if (!cpuinfo) {
> + pr_err("Failed to read /proc/cpuinfo for TSC frequency");
> + return NAN;
> + }
> + while (getline(&line, &len, cpuinfo) > 0) {
> + if (!strncmp(line, "model name", 10)) {
> + char *pos = strstr(line + 11, " @ ");
> +
> + if (pos && sscanf(pos, " @ %lfGHz", &result) == 1) {
> + result *= 1000000000;
> + goto out;
> + }
> + }
> + }
> +out:
> + if (isnan(result))
> + pr_err("Failed to find TSC frequency in /proc/cpuinfo");
> +
> + free(line);
> + fclose(cpuinfo);
> + return result;
> +}
> +
> double expr__get_literal(const char *literal)
> {
> static struct cpu_topology *topology;
> @@ -417,6 +461,11 @@ double expr__get_literal(const char *literal)
> goto out;
> }
>
> + if (!strcasecmp("#system_tsc_freq", literal)) {
> + result = system_tsc_freq();
> + goto out;
> + }
> +
> /*
> * Assume that topology strings are consistent, such as CPUs "0-1"
> * wouldn't be listed as "0,1", and so after deduplication the number of

\
 
 \ /
  Last update: 2022-07-18 14:15    [W:0.099 / U:0.088 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site