xref: /openbmc/linux/tools/perf/bench/syscall.c (revision 3fe91f32620f658adfc073f9df831e7b82498575)
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 		default:
50 			break;
51 		}
52 	}
53 
54 	gettimeofday(&stop, NULL);
55 	timersub(&stop, &start, &diff);
56 
57 	switch (syscall) {
58 	case __NR_getppid:
59 		name = "getppid()";
60 		break;
61 	default:
62 		break;
63 	}
64 
65 	switch (bench_format) {
66 	case BENCH_FORMAT_DEFAULT:
67 		printf("# Executed %'d %s calls\n", loops, name);
68 
69 		result_usec = diff.tv_sec * 1000000;
70 		result_usec += diff.tv_usec;
71 
72 		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
73 		       (unsigned long) diff.tv_sec,
74 		       (unsigned long) (diff.tv_usec/1000));
75 
76 		printf(" %14lf usecs/op\n",
77 		       (double)result_usec / (double)loops);
78 		printf(" %'14d ops/sec\n",
79 		       (int)((double)loops /
80 			     ((double)result_usec / (double)1000000)));
81 		break;
82 
83 	case BENCH_FORMAT_SIMPLE:
84 		printf("%lu.%03lu\n",
85 		       (unsigned long) diff.tv_sec,
86 		       (unsigned long) (diff.tv_usec / 1000));
87 		break;
88 
89 	default:
90 		/* reaching here is something disaster */
91 		fprintf(stderr, "Unknown format:%d\n", bench_format);
92 		exit(1);
93 		break;
94 	}
95 
96 	return 0;
97 }
98 
99 int bench_syscall_basic(int argc, const char **argv)
100 {
101 	return bench_syscall_common(argc, argv, __NR_getppid);
102 }
103