brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 9e4d364 Raw
187 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 18static unsigned int iterations = 100;19 20struct pmu_scan_result {21	char *name;22	int nr_aliases;23	int nr_formats;24	int nr_caps;25	bool is_core;26};27 28static const struct option options[] = {29	OPT_UINTEGER('i', "iterations", &iterations,30		"Number of iterations used to compute average"),31	OPT_END()32};33 34static const char *const bench_usage[] = {35	"perf bench internals pmu-scan <options>",36	NULL37};38 39static int nr_pmus;40static struct pmu_scan_result *results;41 42static 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 75static 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 118static 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 128static 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			else153				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 173int 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