18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Benchmark of /proc/kallsyms parsing.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2020 Google LLC.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <stdlib.h>
88c2ecf20Sopenharmony_ci#include "bench.h"
98c2ecf20Sopenharmony_ci#include "../util/stat.h"
108c2ecf20Sopenharmony_ci#include <linux/time64.h>
118c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h>
128c2ecf20Sopenharmony_ci#include <symbol/kallsyms.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic unsigned int iterations = 100;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic const struct option options[] = {
178c2ecf20Sopenharmony_ci	OPT_UINTEGER('i', "iterations", &iterations,
188c2ecf20Sopenharmony_ci		"Number of iterations used to compute average"),
198c2ecf20Sopenharmony_ci	OPT_END()
208c2ecf20Sopenharmony_ci};
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const char *const bench_usage[] = {
238c2ecf20Sopenharmony_ci	"perf bench internals kallsyms-parse <options>",
248c2ecf20Sopenharmony_ci	NULL
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int bench_process_symbol(void *arg __maybe_unused,
288c2ecf20Sopenharmony_ci				const char *name __maybe_unused,
298c2ecf20Sopenharmony_ci				char type __maybe_unused,
308c2ecf20Sopenharmony_ci				u64 start __maybe_unused)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	return 0;
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int do_kallsyms_parse(void)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	struct timeval start, end, diff;
388c2ecf20Sopenharmony_ci	u64 runtime_us;
398c2ecf20Sopenharmony_ci	unsigned int i;
408c2ecf20Sopenharmony_ci	double time_average, time_stddev;
418c2ecf20Sopenharmony_ci	int err;
428c2ecf20Sopenharmony_ci	struct stats time_stats;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	init_stats(&time_stats);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	for (i = 0; i < iterations; i++) {
478c2ecf20Sopenharmony_ci		gettimeofday(&start, NULL);
488c2ecf20Sopenharmony_ci		err = kallsyms__parse("/proc/kallsyms", NULL,
498c2ecf20Sopenharmony_ci				bench_process_symbol);
508c2ecf20Sopenharmony_ci		if (err)
518c2ecf20Sopenharmony_ci			return err;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		gettimeofday(&end, NULL);
548c2ecf20Sopenharmony_ci		timersub(&end, &start, &diff);
558c2ecf20Sopenharmony_ci		runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
568c2ecf20Sopenharmony_ci		update_stats(&time_stats, runtime_us);
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	time_average = avg_stats(&time_stats) / USEC_PER_MSEC;
608c2ecf20Sopenharmony_ci	time_stddev = stddev_stats(&time_stats) / USEC_PER_MSEC;
618c2ecf20Sopenharmony_ci	printf("  Average kallsyms__parse took: %.3f ms (+- %.3f ms)\n",
628c2ecf20Sopenharmony_ci		time_average, time_stddev);
638c2ecf20Sopenharmony_ci	return 0;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ciint bench_kallsyms_parse(int argc, const char **argv)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	argc = parse_options(argc, argv, options, bench_usage, 0);
698c2ecf20Sopenharmony_ci	if (argc) {
708c2ecf20Sopenharmony_ci		usage_with_options(bench_usage, options);
718c2ecf20Sopenharmony_ci		exit(EXIT_FAILURE);
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	return do_kallsyms_parse();
758c2ecf20Sopenharmony_ci}
76