1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Benchmark synthesis of perf events such as at the start of a 'perf 4 * record'. Synthesis is done on the current process and the 'dummy' event 5 * handlers are invoked that support dump_trace but otherwise do nothing. 6 * 7 * Copyright 2019 Google LLC. 8 */ 9 #include <stdio.h> 10 #include "bench.h" 11 #include "../util/debug.h" 12 #include "../util/session.h" 13 #include "../util/synthetic-events.h" 14 #include "../util/target.h" 15 #include "../util/thread_map.h" 16 #include "../util/tool.h" 17 #include <linux/err.h> 18 #include <linux/time64.h> 19 #include <subcmd/parse-options.h> 20 21 static unsigned int iterations = 10000; 22 23 static const struct option options[] = { 24 OPT_UINTEGER('i', "iterations", &iterations, 25 "Number of iterations used to compute average"), 26 OPT_END() 27 }; 28 29 static const char *const usage[] = { 30 "perf bench internals synthesize <options>", 31 NULL 32 }; 33 34 35 static int do_synthesize(struct perf_session *session, 36 struct perf_thread_map *threads, 37 struct target *target, bool data_mmap) 38 { 39 const unsigned int nr_threads_synthesize = 1; 40 struct timeval start, end, diff; 41 u64 runtime_us; 42 unsigned int i; 43 double average; 44 int err; 45 46 gettimeofday(&start, NULL); 47 for (i = 0; i < iterations; i++) { 48 err = machine__synthesize_threads(&session->machines.host, 49 target, threads, data_mmap, 50 nr_threads_synthesize); 51 if (err) 52 return err; 53 } 54 55 gettimeofday(&end, NULL); 56 timersub(&end, &start, &diff); 57 runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec; 58 average = (double)runtime_us/(double)iterations; 59 printf("Average %ssynthesis took: %f usec\n", 60 data_mmap ? "data " : "", average); 61 return 0; 62 } 63 64 int bench_synthesize(int argc, const char **argv) 65 { 66 struct perf_tool tool; 67 struct perf_session *session; 68 struct target target = { 69 .pid = "self", 70 }; 71 struct perf_thread_map *threads; 72 int err; 73 74 argc = parse_options(argc, argv, options, usage, 0); 75 76 session = perf_session__new(NULL, false, NULL); 77 if (IS_ERR(session)) { 78 pr_err("Session creation failed.\n"); 79 return PTR_ERR(session); 80 } 81 threads = thread_map__new_by_pid(getpid()); 82 if (!threads) { 83 pr_err("Thread map creation failed.\n"); 84 err = -ENOMEM; 85 goto err_out; 86 } 87 perf_tool__fill_defaults(&tool); 88 89 err = do_synthesize(session, threads, &target, false); 90 if (err) 91 goto err_out; 92 93 err = do_synthesize(session, threads, &target, true); 94 95 err_out: 96 if (threads) 97 perf_thread_map__put(threads); 98 99 perf_session__delete(session); 100 return err; 101 } 102