xref: /openbmc/linux/tools/perf/bench/syscall.c (revision 391f84e5555c20a5b5ca4a2b0c3daec383765a09)
1 /*
2  *
3  * syscall.c
4  *
5  * syscall: Benchmark for system call performance
6  */
7 #include "../perf.h"
8 #include "../util/util.h"
9 #include <subcmd/parse-options.h>
10 #include "../builtin.h"
11 #include "bench.h"
12 
13 #include <stdio.h>
14 #include <sys/time.h>
15 #include <sys/syscall.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 
20 #define LOOPS_DEFAULT 10000000
21 static	int loops = LOOPS_DEFAULT;
22 
23 static const struct option options[] = {
24 	OPT_INTEGER('l', "loop",	&loops,		"Specify number of loops"),
25 	OPT_END()
26 };
27 
28 static const char * const bench_syscall_usage[] = {
29 	"perf bench syscall <options>",
30 	NULL
31 };
32 
33 static int bench_syscall_common(int argc, const char **argv, int syscall)
34 {
35 	struct timeval start, stop, diff;
36 	unsigned long long result_usec = 0;
37 	const char *name = NULL;
38 	int i;
39 
40 	argc = parse_options(argc, argv, options, bench_syscall_usage, 0);
41 
42 	gettimeofday(&start, NULL);
43 
44 	for (i = 0; i < loops; i++) {
45 		switch (syscall) {
46 		case __NR_getppid:
47 			getppid();
48 			break;
49 		case __NR_getpgid:
50 			getpgid(0);
51 			break;
52 		default:
53 			break;
54 		}
55 	}
56 
57 	gettimeofday(&stop, NULL);
58 	timersub(&stop, &start, &diff);
59 
60 	switch (syscall) {
61 	case __NR_getppid:
62 		name = "getppid()";
63 		break;
64 	case __NR_getpgid:
65 		name = "getpgid()";
66 		break;
67 	default:
68 		break;
69 	}
70 
71 	switch (bench_format) {
72 	case BENCH_FORMAT_DEFAULT:
73 		printf("# Executed %'d %s calls\n", loops, name);
74 
75 		result_usec = diff.tv_sec * 1000000;
76 		result_usec += diff.tv_usec;
77 
78 		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
79 		       (unsigned long) diff.tv_sec,
80 		       (unsigned long) (diff.tv_usec/1000));
81 
82 		printf(" %14lf usecs/op\n",
83 		       (double)result_usec / (double)loops);
84 		printf(" %'14d ops/sec\n",
85 		       (int)((double)loops /
86 			     ((double)result_usec / (double)1000000)));
87 		break;
88 
89 	case BENCH_FORMAT_SIMPLE:
90 		printf("%lu.%03lu\n",
91 		       (unsigned long) diff.tv_sec,
92 		       (unsigned long) (diff.tv_usec / 1000));
93 		break;
94 
95 	default:
96 		/* reaching here is something disaster */
97 		fprintf(stderr, "Unknown format:%d\n", bench_format);
98 		exit(1);
99 		break;
100 	}
101 
102 	return 0;
103 }
104 
105 int bench_syscall_basic(int argc, const char **argv)
106 {
107 	return bench_syscall_common(argc, argv, __NR_getppid);
108 }
109 
110 int bench_syscall_getpgid(int argc, const char **argv)
111 {
112 	return bench_syscall_common(argc, argv, __NR_getpgid);
113 }
114