Date: Wed, 3 Feb 2010 00:08:18 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 174200 for review Message-ID: <201002030008.o1308IEW042070@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=174200 Change 174200 by rwatson@rwatson_vimage_client on 2010/02/03 00:07:51 Rework syscall timing microbenchmark to make it a bit more flexible, add some capability-related tests. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/tools/tools/syscall_timing/Makefile#2 edit .. //depot/projects/trustedbsd/capabilities/src/tools/tools/syscall_timing/syscall_timing.c#2 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/tools/tools/syscall_timing/Makefile#2 (text+ko) ==== @@ -3,7 +3,7 @@ # PROG= syscall_timing -CFLAGS+= -static -O +CFLAGS+= -static -O -Wall NO_MAN= .include <bsd.prog.mk> ==== //depot/projects/trustedbsd/capabilities/src/tools/tools/syscall_timing/syscall_timing.c#2 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003-2004 Robert N. M. Watson + * Copyright (c) 2003-2004, 2010 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,15 +27,23 @@ */ #include <sys/types.h> +#include <sys/capability.h> +#include <sys/mman.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/time.h> #include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +static struct timespec ts_start, ts_end; + #define timespecsub(vvp, uvp) \ do { \ (vvp)->tv_sec -= (uvp)->tv_sec; \ @@ -46,7 +54,21 @@ } \ } while (0) -inline void +static void +benchmark_start(void) +{ + + assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); +} + +static void +benchmark_stop(void) +{ + + assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); +} + +void test_getuid(int num) { int i; @@ -55,11 +77,13 @@ * Thread-local data should require no locking if system * call is MPSAFE. */ + benchmark_start(); for (i = 0; i < num; i++) getuid(); + benchmark_stop(); } -inline void +void test_getppid(int num) { int i; @@ -68,28 +92,28 @@ * This is process-local, but can change, so will require a * lock. */ + benchmark_start(); for (i = 0; i < num; i++) getppid(); + benchmark_stop(); } -inline void +void test_clock_gettime(int num) { struct timespec ts; int i; - for (i = 0; i < num; i++) { - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { - perror("clock_gettime"); - exit(-1); - } - } + benchmark_start(); + for (i = 0; i < num; i++) + (void)clock_gettime(CLOCK_REALTIME, &ts); + benchmark_stop(); } -inline void +void test_pipe(int num) { - int i; + int fd[2], i; /* * pipe creation is expensive, as it will allocate a new file @@ -97,144 +121,241 @@ * Destroying is also expensive, as we now have to free up * the file descriptors and return the pipe. */ + if (pipe(fd) < 0) + err(-1, "test_pipe: pipe"); + close(fd[0]); + close(fd[1]); + benchmark_start(); for (i = 0; i < num; i++) { - int fd[2]; - if (pipe(fd) == -1) { - perror("pipe"); - exit(-1); - } - + if (pipe(fd) == -1) + err(-1, "test_pipe: pipe"); close(fd[0]); close(fd[1]); } + benchmark_stop(); } -inline void +void test_socket_stream(int num) { int i, so; + so = socket(PF_LOCAL, SOCK_STREAM, 0); + if (so < 0) + err(-1, "test_socket_stream: socket"); + close(so); + benchmark_start(); for (i = 0; i < num; i++) { so = socket(PF_LOCAL, SOCK_STREAM, 0); - if (so == -1) { - perror("socket_stream"); - exit(-1); - } + if (so == -1) + err(-1, "test_socket_stream: socket"); close(so); } + benchmark_stop(); } -inline void +void test_socket_dgram(int num) { int i, so; + so = socket(PF_LOCAL, SOCK_DGRAM, 0); + if (so < 0) + err(-1, "test_socket_dgram: socket"); + close(so); + benchmark_start(); for (i = 0; i < num; i++) { so = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (so == -1) { - perror("socket_dgram"); - exit(-1); - } + if (so == -1) + err(-1, "test_socket_dgram: socket"); close(so); } + benchmark_stop(); } -inline void +void test_socketpair_stream(int num) { int i, so[2]; + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1) + err(-1, "test_socketpair_stream: socketpair"); + close(so[0]); + close(so[1]); + benchmark_start(); for (i = 0; i < num; i++) { - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1) { - perror("socketpair_stream"); - exit(-1); - } + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, so) == -1) + err(-1, "test_socketpair_stream: socketpair"); close(so[0]); close(so[1]); } + benchmark_stop(); } -inline void +void test_socketpair_dgram(int num) { int i, so[2]; + if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1) + err(-1, "test_socketpair_dgram: socketpair"); + close(so[0]); + close(so[1]); + benchmark_start(); for (i = 0; i < num; i++) { - if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1) { - perror("socketpair_dgram"); - exit(-1); - } + if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, so) == -1) + err(-1, "test_socketpair_dgram: socketpair"); close(so[0]); close(so[1]); } + benchmark_stop(); } +void +test_dup(int num) +{ + int fd, i, shmfd; + + shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); + if (shmfd < 0) + err(-1, "test_dup: shm_open"); + fd = dup(shmfd); + if (fd >= 0) + close(fd); + benchmark_start(); + for (i = 0; i < num; i++) { + fd = dup(shmfd); + if (fd >= 0) + close(fd); + } + benchmark_stop(); + close(shmfd); +} + +void +test_cap_new(int num) +{ + int fd, i, shmfd; + + shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); + if (shmfd < 0) + err(-1, "test_cap_new: shm_open"); + fd = cap_new(shmfd, 0); + if (fd >= 0) + close(fd); + benchmark_start(); + for (i = 0; i < num; i++) { + fd = cap_new(shmfd, 0); + if (fd >= 0) + close(fd); + } + benchmark_stop(); + close(shmfd); +} + +void +test_fstat_shmfd(int num) +{ + struct stat sb; + int i, shmfd; + + shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); + if (shmfd < 0) + err(-1, "test_fstat_shmfd: shm_open"); + if (fstat(shmfd, &sb) < 0) + err(-1, "test_fstat_shmfd: fstat"); + benchmark_start(); + for (i = 0; i < num; i++) + (void)fstat(shmfd, &sb); + benchmark_stop(); + close(shmfd); +} + +void +test_fstat_cap_shmfd(int num) +{ + struct stat sb; + int fd, i, shmfd; + + shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); + if (shmfd < 0) + err(-1, "test_fstat_cap_shmfd: shm_open"); + fd = cap_new(shmfd, CAP_FSTAT); + if (fd < 0) + err(-1, "test_fstat_cap_shmfd: shm_open"); + if (fstat(fd, &sb) < 0) + err(-1, "test_fstat_cap_shmfd: fstat"); + benchmark_start(); + for (i = 0; i < num; i++) + (void)fstat(fd, &sb); + benchmark_stop(); + close(fd); + close(shmfd); +} + +struct test { + const char *t_name; + void (*t_func)(int); +}; + +static const struct test tests[] = { + { "getuid", test_getuid }, + { "getppid", test_getppid }, + { "clock_gettime", test_clock_gettime }, + { "pipe", test_pipe }, + { "socket_stream", test_socket_stream }, + { "socket_dgram", test_socket_dgram }, + { "socketpair_stream", test_socketpair_stream }, + { "socketpair_dgram", test_socketpair_dgram }, + { "dup", test_dup }, + { "cap_new", test_cap_new }, + { "fstat_shmfd", test_fstat_shmfd }, + { "fstat_cap_shmfd", test_fstat_cap_shmfd }, +}; +static const int tests_count = sizeof(tests) / sizeof(tests[0]); + static void usage(void) { + int i; fprintf(stderr, "syscall_timing [iterations] [test]\n"); - fprintf(stderr, - "supported tests: getuid getppid clock_gettime pipe\n" - "socket_stream socket_dgram socketpair_stream\n" - "socketpair_dgram\n"); + for (i = 0; i < tests_count; i++) + fprintf(stderr, " %s\n", tests[i].t_name); exit(-1); } int main(int argc, char *argv[]) { - struct timespec ts_start, ts_end, ts_res; - int count; + struct timespec ts_res; + const struct test *the_test; + int count, i; if (argc != 3) usage(); count = atoi(argv[1]); assert(clock_getres(CLOCK_REALTIME, &ts_res) == 0); - printf("Clock resolution: %d.%09lu\n", ts_res.tv_sec, ts_res.tv_nsec); + printf("Clock resolution: %ju.%ju\n", (uintmax_t)ts_res.tv_sec, + (uintmax_t)ts_res.tv_nsec); - if (strcmp(argv[2], "getuid") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_getuid(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "getppid") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_getppid(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "clock_gettime") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_clock_gettime(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "pipe") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_pipe(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "socket_stream") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_socket_stream(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "socket_dgram") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_socket_dgram(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "socketpair_stream") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_socketpair_stream(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else if (strcmp(argv[2], "socketpair_dgram") == 0) { - assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0); - test_socketpair_dgram(count); - assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0); - } else + the_test = NULL; + for (i = 0; i < tests_count; i++) { + if (strcmp(argv[2], tests[i].t_name) == 0) + the_test = &tests[i]; + } + if (the_test == NULL) usage(); + the_test->t_func(count); + timespecsub(&ts_end, &ts_start); printf("test: %s\n", argv[2]); - printf("%d.%09lu for %d iterations\n", ts_end.tv_sec, - ts_end.tv_nsec, count); + printf("%ju.%09ju for %d iterations\n", (uintmax_t)ts_end.tv_sec, + (uintmax_t)ts_end.tv_nsec, count); /* * Note. This assumes that each iteration takes less than @@ -243,7 +364,7 @@ * but not for long things. */ ts_end.tv_sec *= 1000000000 / count; - printf("0.%09lu per/iteration\n", - ts_end.tv_sec + ts_end.tv_nsec / count); + printf("0.%09ju per/iteration\n", + (uintmax_t)(ts_end.tv_sec + ts_end.tv_nsec / count)); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002030008.o1308IEW042070>