brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · ea4dfc0 Raw
185 lines · c
1/*2 *3 * syscall.c4 *5 * syscall: Benchmark for system call performance6 */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 <sys/wait.h>18#include <unistd.h>19#include <stdlib.h>20 21#ifndef __NR_fork22#define __NR_fork -123#endif24 25#define LOOPS_DEFAULT 1000000026static	int loops = LOOPS_DEFAULT;27 28static const struct option options[] = {29	OPT_INTEGER('l', "loop",	&loops,		"Specify number of loops"),30	OPT_END()31};32 33static const char * const bench_syscall_usage[] = {34	"perf bench syscall <options>",35	NULL36};37 38static void test_fork(void)39{40	pid_t pid = fork();41 42	if (pid < 0) {43		fprintf(stderr, "fork failed\n");44		exit(1);45	} else if (pid == 0) {46		exit(0);47	} else {48		if (waitpid(pid, NULL, 0) < 0) {49			fprintf(stderr, "waitpid failed\n");50			exit(1);51		}52	}53}54 55static void test_execve(void)56{57	const char *pathname = "/bin/true";58	char *const argv[] = { (char *)pathname, NULL };59	pid_t pid = fork();60 61	if (pid < 0) {62		fprintf(stderr, "fork failed\n");63		exit(1);64	} else if (pid == 0) {65		execve(pathname, argv, NULL);66		fprintf(stderr, "execve /bin/true failed\n");67		exit(1);68	} else {69		if (waitpid(pid, NULL, 0) < 0) {70			fprintf(stderr, "waitpid failed\n");71			exit(1);72		}73	}74}75 76static int bench_syscall_common(int argc, const char **argv, int syscall)77{78	struct timeval start, stop, diff;79	unsigned long long result_usec = 0;80	const char *name = NULL;81	int i;82 83	argc = parse_options(argc, argv, options, bench_syscall_usage, 0);84 85	gettimeofday(&start, NULL);86 87	for (i = 0; i < loops; i++) {88		switch (syscall) {89		case __NR_getppid:90			getppid();91			break;92		case __NR_getpgid:93			getpgid(0);94			break;95		case __NR_fork:96			test_fork();97			/* Only loop 10000 times to save time */98			if (i == 10000)99				loops = 10000;100			break;101		case __NR_execve:102			test_execve();103			/* Only loop 10000 times to save time */104			if (i == 10000)105				loops = 10000;106			break;107		default:108			break;109		}110	}111 112	gettimeofday(&stop, NULL);113	timersub(&stop, &start, &diff);114 115	switch (syscall) {116	case __NR_getppid:117		name = "getppid()";118		break;119	case __NR_getpgid:120		name = "getpgid()";121		break;122	case __NR_fork:123		name = "fork()";124		break;125	case __NR_execve:126		name = "execve()";127		break;128	default:129		break;130	}131 132	switch (bench_format) {133	case BENCH_FORMAT_DEFAULT:134		printf("# Executed %'d %s calls\n", loops, name);135 136		result_usec = diff.tv_sec * 1000000;137		result_usec += diff.tv_usec;138 139		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",140		       (unsigned long) diff.tv_sec,141		       (unsigned long) (diff.tv_usec/1000));142 143		printf(" %14lf usecs/op\n",144		       (double)result_usec / (double)loops);145		printf(" %'14d ops/sec\n",146		       (int)((double)loops /147			     ((double)result_usec / (double)1000000)));148		break;149 150	case BENCH_FORMAT_SIMPLE:151		printf("%lu.%03lu\n",152		       (unsigned long) diff.tv_sec,153		       (unsigned long) (diff.tv_usec / 1000));154		break;155 156	default:157		/* reaching here is something disaster */158		fprintf(stderr, "Unknown format:%d\n", bench_format);159		exit(1);160		break;161	}162 163	return 0;164}165 166int bench_syscall_basic(int argc, const char **argv)167{168	return bench_syscall_common(argc, argv, __NR_getppid);169}170 171int bench_syscall_getpgid(int argc, const char **argv)172{173	return bench_syscall_common(argc, argv, __NR_getpgid);174}175 176int bench_syscall_fork(int argc, const char **argv)177{178	return bench_syscall_common(argc, argv, __NR_fork);179}180 181int bench_syscall_execve(int argc, const char **argv)182{183	return bench_syscall_common(argc, argv, __NR_execve);184}185