summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-09-30 05:25:00 +0000
committerrwatson <rwatson@FreeBSD.org>2004-09-30 05:25:00 +0000
commitaf519fd928ba2cf920308f8e8c000beeeb35f6e9 (patch)
treede848b5b3b01e41db59dbaf6d0b55a519fd8105e /tools
parent0bb82cb8b23deaf1c07ba490bda42522953cd7d1 (diff)
downloadFreeBSD-src-af519fd928ba2cf920308f8e8c000beeeb35f6e9.zip
FreeBSD-src-af519fd928ba2cf920308f8e8c000beeeb35f6e9.tar.gz
Add syscall_timing, a simple timing micro-benchmark for some
characteristic system calls. I've been sending this to people for a while, and figured it would be more efficient to just put it in CVS.
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/syscall_timing/Makefile9
-rw-r--r--tools/tools/syscall_timing/syscall_timing.c186
2 files changed, 195 insertions, 0 deletions
diff --git a/tools/tools/syscall_timing/Makefile b/tools/tools/syscall_timing/Makefile
new file mode 100644
index 0000000..0ebdb0e
--- /dev/null
+++ b/tools/tools/syscall_timing/Makefile
@@ -0,0 +1,9 @@
+#
+# $FreeBSD$
+#
+
+PROG= syscall_timing
+CFLAGS+= -static -O
+NOMAN= yes
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/syscall_timing/syscall_timing.c b/tools/tools/syscall_timing/syscall_timing.c
new file mode 100644
index 0000000..5e44a94
--- /dev/null
+++ b/tools/tools/syscall_timing/syscall_timing.c
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2003-2004 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define timespecsub(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec -= (uvp)->tv_sec; \
+ (vvp)->tv_nsec -= (uvp)->tv_nsec; \
+ if ((vvp)->tv_nsec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+
+inline void
+test_getuid(int num)
+{
+ int i;
+
+ /*
+ * Thread-local data should require no locking if system
+ * call is MPSAFE.
+ */
+ for (i = 0; i < num; i++)
+ getuid();
+}
+
+inline void
+test_getppid(int num)
+{
+ int i;
+
+ /*
+ * This is process-local, but can change, so will require a
+ * lock.
+ */
+ for (i = 0; i < num; i++)
+ getppid();
+}
+
+inline 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);
+ }
+ }
+}
+
+inline void
+test_pipe(int num)
+{
+ int i;
+
+ /*
+ * pipe creation is expensive, as it will allocate a new file
+ * descriptor, allocate a new pipe, hook it all up, and return.
+ * Destroying is also expensive, as we now have to free up
+ * the file descriptors and return the pipe.
+ */
+ for (i = 0; i < num; i++) {
+ int fd[2];
+ if (pipe(fd) == -1) {
+ perror("pipe");
+ exit(-1);
+ }
+
+ close(fd[0]);
+ close(fd[1]);
+ }
+}
+
+inline void
+test_socket(int num)
+{
+ int i, so;
+
+ /*
+ * Sockets are also expensive, but unlike pipes, currently
+ * require Giant.
+ */
+ for (i = 0; i < num; i++) {
+ so = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (so == -1) {
+ perror("socket");
+ exit(-1);
+ }
+ close(so);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct timespec ts_start, ts_end, ts_res;
+ int count;
+
+ if (argc != 3) {
+ fprintf(stderr, "syscall_timing [iterations] [test]\n");
+ exit(-1);
+ }
+ 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);
+
+ 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") == 0) {
+ assert(clock_gettime(CLOCK_REALTIME, &ts_start) == 0);
+ test_socket(count);
+ assert(clock_gettime(CLOCK_REALTIME, &ts_end) == 0);
+ } else {
+ fprintf(stderr, "syscal [iterations] [test]\n");
+ exit(-1);
+ }
+
+ timespecsub(&ts_end, &ts_start);
+
+ printf("%d.%09lu for %d iterations\n", ts_end.tv_sec,
+ ts_end.tv_nsec, count);
+
+ /*
+ * Note. This assumes that each iteration takes less than
+ * a second, and that our total nanoseconds doesn't exceed
+ * the room in our arithmetic unit. Fine for system calls,
+ * 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);
+ return (0);
+}
OpenPOWER on IntegriCloud