~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/bench/pmu-scan.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Benchmark scanning sysfs files for PMU information.
  4  *
  5  * Copyright 2023 Google LLC.
  6  */
  7 #include <stdio.h>
  8 #include "bench.h"
  9 #include "util/debug.h"
 10 #include "util/pmu.h"
 11 #include "util/pmus.h"
 12 #include "util/stat.h"
 13 #include <linux/atomic.h>
 14 #include <linux/err.h>
 15 #include <linux/time64.h>
 16 #include <subcmd/parse-options.h>
 17 
 18 static unsigned int iterations = 100;
 19 
 20 struct pmu_scan_result {
 21         char *name;
 22         int nr_aliases;
 23         int nr_formats;
 24         int nr_caps;
 25         bool is_core;
 26 };
 27 
 28 static const struct option options[] = {
 29         OPT_UINTEGER('i', "iterations", &iterations,
 30                 "Number of iterations used to compute average"),
 31         OPT_END()
 32 };
 33 
 34 static const char *const bench_usage[] = {
 35         "perf bench internals pmu-scan <options>",
 36         NULL
 37 };
 38 
 39 static int nr_pmus;
 40 static struct pmu_scan_result *results;
 41 
 42 static int save_result(void)
 43 {
 44         struct perf_pmu *pmu = NULL;
 45         struct list_head *list;
 46         struct pmu_scan_result *r;
 47 
 48         while ((pmu = perf_pmus__scan(pmu)) != NULL) {
 49                 r = realloc(results, (nr_pmus + 1) * sizeof(*r));
 50                 if (r == NULL)
 51                         return -ENOMEM;
 52 
 53                 results = r;
 54                 r = results + nr_pmus;
 55 
 56                 r->name = strdup(pmu->name);
 57                 r->is_core = pmu->is_core;
 58                 r->nr_caps = pmu->nr_caps;
 59 
 60                 r->nr_aliases = perf_pmu__num_events(pmu);
 61 
 62                 r->nr_formats = 0;
 63                 list_for_each(list, &pmu->format)
 64                         r->nr_formats++;
 65 
 66                 pr_debug("pmu[%d] name=%s, nr_caps=%d, nr_aliases=%d, nr_formats=%d\n",
 67                         nr_pmus, r->name, r->nr_caps, r->nr_aliases, r->nr_formats);
 68                 nr_pmus++;
 69         }
 70 
 71         perf_pmus__destroy();
 72         return 0;
 73 }
 74 
 75 static int check_result(bool core_only)
 76 {
 77         struct pmu_scan_result *r;
 78         struct perf_pmu *pmu;
 79         struct list_head *list;
 80         int nr;
 81 
 82         for (int i = 0; i < nr_pmus; i++) {
 83                 r = &results[i];
 84                 if (core_only && !r->is_core)
 85                         continue;
 86 
 87                 pmu = perf_pmus__find(r->name);
 88                 if (pmu == NULL) {
 89                         pr_err("Cannot find PMU %s\n", r->name);
 90                         return -1;
 91                 }
 92 
 93                 if (pmu->nr_caps != (u32)r->nr_caps) {
 94                         pr_err("Unmatched number of event caps in %s: expect %d vs got %d\n",
 95                                 pmu->name, r->nr_caps, pmu->nr_caps);
 96                         return -1;
 97                 }
 98 
 99                 nr = perf_pmu__num_events(pmu);
100                 if (nr != r->nr_aliases) {
101                         pr_err("Unmatched number of event aliases in %s: expect %d vs got %d\n",
102                                 pmu->name, r->nr_aliases, nr);
103                         return -1;
104                 }
105 
106                 nr = 0;
107                 list_for_each(list, &pmu->format)
108                         nr++;
109                 if (nr != r->nr_formats) {
110                         pr_err("Unmatched number of event formats in %s: expect %d vs got %d\n",
111                                 pmu->name, r->nr_formats, nr);
112                         return -1;
113                 }
114         }
115         return 0;
116 }
117 
118 static void delete_result(void)
119 {
120         for (int i = 0; i < nr_pmus; i++)
121                 free(results[i].name);
122         free(results);
123 
124         results = NULL;
125         nr_pmus = 0;
126 }
127 
128 static int run_pmu_scan(void)
129 {
130         struct stats stats;
131         struct timeval start, end, diff;
132         double time_average, time_stddev;
133         u64 runtime_us;
134         int ret;
135 
136         init_stats(&stats);
137         pr_info("Computing performance of sysfs PMU event scan for %u times\n",
138                 iterations);
139 
140         if (save_result() < 0) {
141                 pr_err("Failed to initialize PMU scan result\n");
142                 return -1;
143         }
144 
145         for (int j = 0; j < 2; j++) {
146                 bool core_only = (j == 0);
147 
148                 for (unsigned int i = 0; i < iterations; i++) {
149                         gettimeofday(&start, NULL);
150                         if (core_only)
151                                 perf_pmus__scan_core(NULL);
152                         else
153                                 perf_pmus__scan(NULL);
154                         gettimeofday(&end, NULL);
155                         timersub(&end, &start, &diff);
156                         runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
157                         update_stats(&stats, runtime_us);
158 
159                         ret = check_result(core_only);
160                         perf_pmus__destroy();
161                         if (ret < 0)
162                                 break;
163                 }
164                 time_average = avg_stats(&stats);
165                 time_stddev = stddev_stats(&stats);
166                 pr_info("  Average%s PMU scanning took: %.3f usec (+- %.3f usec)\n",
167                         core_only ? " core" : "", time_average, time_stddev);
168         }
169         delete_result();
170         return 0;
171 }
172 
173 int bench_pmu_scan(int argc, const char **argv)
174 {
175         int err = 0;
176 
177         argc = parse_options(argc, argv, options, bench_usage, 0);
178         if (argc) {
179                 usage_with_options(bench_usage, options);
180                 exit(EXIT_FAILURE);
181         }
182 
183         err = run_pmu_scan();
184 
185         return err;
186 }
187 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php