svn rev #23523: trunk/src/tests/threads/
raeburn@MIT.EDU
raeburn at MIT.EDU
Sun Dec 27 19:21:16 EST 2009
http://src.mit.edu/fisheye/changelog/krb5/?cs=23523
Commit By: raeburn
Log Message:
Performance testing programs for krb5_init_context and profile data fetch.
Changed Files:
U trunk/src/tests/threads/Makefile.in
A trunk/src/tests/threads/init_ctx.c
A trunk/src/tests/threads/profread.c
Modified: trunk/src/tests/threads/Makefile.in
===================================================================
--- trunk/src/tests/threads/Makefile.in 2009-12-28 00:21:13 UTC (rev 23522)
+++ trunk/src/tests/threads/Makefile.in 2009-12-28 00:21:16 UTC (rev 23523)
@@ -7,6 +7,8 @@
SRCS=$(srcdir)/t_rcache.c \
$(srcdir)/gss-perf.c \
+ $(srcdir)/init_ctx.c \
+ $(srcdir)/profread.c \
$(srcdir)/prof1.c
all::
@@ -23,9 +25,15 @@
prof1.o: prof1.c
-gss-perf: gss-perf.o
+gss-perf: gss-perf.o $(KRB5_BASE_DEPLIBS) $(GSS_DEPLIBS)
$(CC_LINK) $(PTHREAD_CFLAGS) -o gss-perf gss-perf.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+init_ctx: init_ctx.o $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) $(PTHREAD_CFLAGS) -o init_ctx init_ctx.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
+profread: profread.o $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) $(PTHREAD_CFLAGS) -o profread profread.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS)
+
check-unix:: run-t_rcache
install::
Added: trunk/src/tests/threads/init_ctx.c
===================================================================
--- trunk/src/tests/threads/init_ctx.c (rev 0)
+++ trunk/src/tests/threads/init_ctx.c 2009-12-28 00:21:16 UTC (rev 23523)
@@ -0,0 +1,278 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * test/threads/init_ctx.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * krb5 context creation performance testing
+ * initially contributed by Ken Raeburn
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <krb5.h>
+/* for SIZE_MAX: */
+#include "k5-platform.h"
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#define N_THREADS 4
+#define ITER_COUNT 40000
+static int init_krb5_first = 0;
+
+struct resource_info {
+ struct timeval start_time, end_time;
+};
+struct thread_info {
+ pthread_t tid;
+ struct resource_info r;
+};
+
+static char *prog;
+static unsigned int n_threads = N_THREADS;
+static int iter_count = ITER_COUNT;
+static int do_pause;
+
+static void usage (void) __attribute__((noreturn));
+
+static void
+usage ()
+{
+ fprintf (stderr, "usage: %s [ options ]\n", prog);
+ fprintf (stderr, "options:\n");
+ fprintf (stderr, "\t-t N\tspecify number of threads (default %d)\n",
+ N_THREADS);
+ fprintf (stderr, "\t-i N\tset iteration count (default %d)\n",
+ ITER_COUNT);
+ fprintf (stderr, "\t-K\tinitialize a krb5_context for the duration\n");
+ fprintf (stderr, "\t-P\tpause briefly after starting, to allow attaching dtrace/strace/etc\n");
+ exit (1);
+}
+
+static int
+numarg (char *arg)
+{
+ char *end;
+ long val;
+
+ val = strtol (arg, &end, 10);
+ if (*arg == 0 || *end != 0) {
+ fprintf (stderr, "invalid numeric argument '%s'\n", arg);
+ usage ();
+ }
+ if (val >= 1 && val <= INT_MAX)
+ return val;
+ fprintf (stderr, "out of range numeric value %ld (1..%d)\n",
+ val, INT_MAX);
+ usage ();
+}
+
+static char optstring[] = "t:i:KP";
+
+static void
+process_options (int argc, char *argv[])
+{
+ int c;
+
+ prog = strrchr (argv[0], '/');
+ if (prog)
+ prog++;
+ else
+ prog = argv[0];
+ while ((c = getopt (argc, argv, optstring)) != -1) {
+ switch (c) {
+ case '?':
+ case ':':
+ usage ();
+ break;
+
+ case 't':
+ n_threads = numarg (optarg);
+ if (n_threads >= SIZE_MAX / sizeof (struct thread_info)) {
+ n_threads = SIZE_MAX / sizeof (struct thread_info);
+ fprintf (stderr, "limiting n_threads to %u\n", n_threads);
+ }
+ break;
+
+ case 'i':
+ iter_count = numarg (optarg);
+ break;
+
+ case 'K':
+ init_krb5_first = 1;
+ break;
+
+ case 'P':
+ do_pause = 1;
+ break;
+ }
+ }
+ if (argc != optind)
+ usage ();
+}
+
+static long double
+tvsub (struct timeval t1, struct timeval t2)
+{
+ /* POSIX says .tv_usec is signed. */
+ return (t1.tv_sec - t2.tv_sec
+ + (long double) 1.0e-6 * (t1.tv_usec - t2.tv_usec));
+}
+
+static struct timeval
+now (void)
+{
+ struct timeval tv;
+ if (gettimeofday (&tv, NULL) < 0) {
+ perror ("gettimeofday");
+ exit (1);
+ }
+ return tv;
+}
+
+static void run_iterations (struct resource_info *r)
+{
+ int i;
+ krb5_error_code err;
+ krb5_context ctx;
+
+ r->start_time = now ();
+ for (i = 0; i < iter_count; i++) {
+ err = krb5_init_context(&ctx);
+ if (err) {
+ com_err(prog, err, "initializing krb5 context");
+ exit(1);
+ }
+ krb5_free_context(ctx);
+ }
+ r->end_time = now ();
+}
+
+static void *
+thread_proc (void *p)
+{
+ run_iterations (p);
+ return 0;
+}
+
+static struct thread_info *tinfo;
+
+static krb5_context kctx;
+static struct rusage start, finish;
+static struct timeval start_time, finish_time;
+
+int
+main (int argc, char *argv[])
+{
+ long double user, sys, wallclock, total;
+ unsigned int i;
+
+ process_options (argc, argv);
+
+ /*
+ * Some places in the krb5 library cache data globally.
+ * This option allows you to test the effect of that.
+ */
+ if (init_krb5_first && krb5_init_context (&kctx) != 0) {
+ fprintf (stderr, "krb5_init_context error\n");
+ exit (1);
+ }
+ tinfo = calloc (n_threads, sizeof (*tinfo));
+ if (tinfo == NULL) {
+ perror ("calloc");
+ exit (1);
+ }
+ printf ("Threads: %d iterations: %d\n", n_threads, iter_count);
+ if (do_pause) {
+ printf ("pid %lu napping...\n", (unsigned long) getpid ());
+ sleep (10);
+ }
+ printf ("starting...\n");
+ /* And *now* we start measuring the performance. */
+ if (getrusage (RUSAGE_SELF, &start) < 0) {
+ perror ("getrusage");
+ exit (1);
+ }
+ start_time = now ();
+#define foreach_thread(IDXVAR) for (IDXVAR = 0; IDXVAR < n_threads; IDXVAR++)
+ foreach_thread (i) {
+ int err;
+
+ err = pthread_create (&tinfo[i].tid, NULL, thread_proc, &tinfo[i].r);
+ if (err) {
+ fprintf (stderr, "pthread_create: %s\n", strerror (err));
+ exit (1);
+ }
+ }
+ foreach_thread (i) {
+ int err;
+ void *val;
+
+ err = pthread_join (tinfo[i].tid, &val);
+ if (err) {
+ fprintf (stderr, "pthread_join: %s\n", strerror (err));
+ exit (1);
+ }
+ }
+ finish_time = now ();
+ if (getrusage (RUSAGE_SELF, &finish) < 0) {
+ perror ("getrusage");
+ exit (1);
+ }
+ if (init_krb5_first)
+ krb5_free_context (kctx);
+ foreach_thread (i) {
+ printf ("Thread %2d: elapsed time %Lfs\n", i,
+ tvsub (tinfo[i].r.end_time, tinfo[i].r.start_time));
+ }
+ wallclock = tvsub (finish_time, start_time);
+ /*
+ * Report on elapsed time and CPU usage. Depending what
+ * performance issue you're chasing down, different values may be
+ * of particular interest, so report all the info we've got.
+ */
+ printf ("Overall run time with %d threads = %Lfs, %Lfms per iteration.\n",
+ n_threads, wallclock, 1000 * wallclock / iter_count);
+ user = tvsub (finish.ru_utime, start.ru_utime);
+ sys = tvsub (finish.ru_stime, start.ru_stime);
+ total = user + sys;
+ printf ("CPU usage: user=%Lfs sys=%Lfs total=%Lfs.\n", user, sys, total);
+ printf ("Utilization: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n",
+ 100 * user / wallclock,
+ 100 * sys / wallclock,
+ 100 * total / wallclock);
+ printf ("Util/thread: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n",
+ 100 * user / wallclock / n_threads,
+ 100 * sys / wallclock / n_threads,
+ 100 * total / wallclock / n_threads);
+ printf ("Total CPU use per iteration per thread: %Lfms\n",
+ 1000 * total / n_threads / iter_count);
+ return 0;
+}
Added: trunk/src/tests/threads/profread.c
===================================================================
--- trunk/src/tests/threads/profread.c (rev 0)
+++ trunk/src/tests/threads/profread.c 2009-12-28 00:21:16 UTC (rev 23523)
@@ -0,0 +1,293 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * test/threads/profread.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * krb5 profile data retrieval performance testing
+ * initially contributed by Ken Raeburn
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <krb5.h>
+#include <profile.h>
+/* for SIZE_MAX: */
+#include "k5-platform.h"
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#define N_THREADS 4
+#define ITER_COUNT 40000
+static int init_krb5_first = 0;
+
+struct resource_info {
+ struct timeval start_time, end_time;
+};
+struct thread_info {
+ pthread_t tid;
+ struct resource_info r;
+ krb5_context ctx;
+};
+
+static char *prog;
+static unsigned int n_threads = N_THREADS;
+static int iter_count = ITER_COUNT;
+static int do_pause;
+
+static void usage (void) __attribute__((noreturn));
+
+static void
+usage ()
+{
+ fprintf (stderr, "usage: %s [ options ]\n", prog);
+ fprintf (stderr, "options:\n");
+ fprintf (stderr, "\t-t N\tspecify number of threads (default %d)\n",
+ N_THREADS);
+ fprintf (stderr, "\t-i N\tset iteration count (default %d)\n",
+ ITER_COUNT);
+ fprintf (stderr, "\t-K\tinitialize a krb5_context for the duration\n");
+ fprintf (stderr, "\t-P\tpause briefly after starting, to allow attaching dtrace/strace/etc\n");
+ exit (1);
+}
+
+static int
+numarg (char *arg)
+{
+ char *end;
+ long val;
+
+ val = strtol (arg, &end, 10);
+ if (*arg == 0 || *end != 0) {
+ fprintf (stderr, "invalid numeric argument '%s'\n", arg);
+ usage ();
+ }
+ if (val >= 1 && val <= INT_MAX)
+ return val;
+ fprintf (stderr, "out of range numeric value %ld (1..%d)\n",
+ val, INT_MAX);
+ usage ();
+}
+
+static char optstring[] = "t:i:KP";
+
+static void
+process_options (int argc, char *argv[])
+{
+ int c;
+
+ prog = strrchr (argv[0], '/');
+ if (prog)
+ prog++;
+ else
+ prog = argv[0];
+ while ((c = getopt (argc, argv, optstring)) != -1) {
+ switch (c) {
+ case '?':
+ case ':':
+ usage ();
+ break;
+
+ case 't':
+ n_threads = numarg (optarg);
+ if (n_threads >= SIZE_MAX / sizeof (struct thread_info)) {
+ n_threads = SIZE_MAX / sizeof (struct thread_info);
+ fprintf (stderr, "limiting n_threads to %u\n", n_threads);
+ }
+ break;
+
+ case 'i':
+ iter_count = numarg (optarg);
+ break;
+
+ case 'K':
+ init_krb5_first = 1;
+ break;
+
+ case 'P':
+ do_pause = 1;
+ break;
+ }
+ }
+ if (argc != optind)
+ usage ();
+}
+
+static long double
+tvsub (struct timeval t1, struct timeval t2)
+{
+ /* POSIX says .tv_usec is signed. */
+ return (t1.tv_sec - t2.tv_sec
+ + (long double) 1.0e-6 * (t1.tv_usec - t2.tv_usec));
+}
+
+static struct timeval
+now (void)
+{
+ struct timeval tv;
+ if (gettimeofday (&tv, NULL) < 0) {
+ perror ("gettimeofday");
+ exit (1);
+ }
+ return tv;
+}
+
+static void run_iterations (struct resource_info *r)
+{
+ int i;
+ krb5_error_code err;
+ krb5_context ctx;
+ profile_t prof = NULL;
+
+ err = krb5_init_context(&ctx);
+ if (err) {
+ com_err(prog, err, "initializing krb5 context");
+ exit(1);
+ }
+ err = krb5_get_profile(ctx, &prof);
+ if (err) {
+ com_err(prog, err, "fetching profile from context");
+ exit(1);
+ }
+ r->start_time = now ();
+ for (i = 0; i < iter_count; i++) {
+ int ival;
+ err = profile_get_integer(prof, "one", "two", "three", 42, &ival);
+ if (err) {
+ com_err(prog, err, "fetching value from profile");
+ exit(1);
+ }
+ }
+ r->end_time = now ();
+ profile_release (prof);
+ krb5_free_context(ctx);
+}
+
+static void *
+thread_proc (void *p)
+{
+ run_iterations (p);
+ return 0;
+}
+
+static struct thread_info *tinfo;
+
+static krb5_context kctx;
+static struct rusage start, finish;
+static struct timeval start_time, finish_time;
+
+int
+main (int argc, char *argv[])
+{
+ long double user, sys, wallclock, total;
+ unsigned int i;
+
+ process_options (argc, argv);
+
+ /*
+ * Some places in the krb5 library cache data globally.
+ * This option allows you to test the effect of that.
+ */
+ if (init_krb5_first && krb5_init_context (&kctx) != 0) {
+ fprintf (stderr, "krb5_init_context error\n");
+ exit (1);
+ }
+ tinfo = calloc (n_threads, sizeof (*tinfo));
+ if (tinfo == NULL) {
+ perror ("calloc");
+ exit (1);
+ }
+ printf ("Threads: %d iterations: %d\n", n_threads, iter_count);
+ if (do_pause) {
+ printf ("pid %lu napping...\n", (unsigned long) getpid ());
+ sleep (10);
+ }
+ printf ("starting...\n");
+ /* And *now* we start measuring the performance. */
+ if (getrusage (RUSAGE_SELF, &start) < 0) {
+ perror ("getrusage");
+ exit (1);
+ }
+ start_time = now ();
+#define foreach_thread(IDXVAR) for (IDXVAR = 0; IDXVAR < n_threads; IDXVAR++)
+ foreach_thread (i) {
+ int err;
+
+ err = pthread_create (&tinfo[i].tid, NULL, thread_proc, &tinfo[i].r);
+ if (err) {
+ fprintf (stderr, "pthread_create: %s\n", strerror (err));
+ exit (1);
+ }
+ }
+ foreach_thread (i) {
+ int err;
+ void *val;
+
+ err = pthread_join (tinfo[i].tid, &val);
+ if (err) {
+ fprintf (stderr, "pthread_join: %s\n", strerror (err));
+ exit (1);
+ }
+ }
+ finish_time = now ();
+ if (getrusage (RUSAGE_SELF, &finish) < 0) {
+ perror ("getrusage");
+ exit (1);
+ }
+ if (init_krb5_first)
+ krb5_free_context (kctx);
+ foreach_thread (i) {
+ printf ("Thread %2d: elapsed time %Lfs\n", i,
+ tvsub (tinfo[i].r.end_time, tinfo[i].r.start_time));
+ }
+ wallclock = tvsub (finish_time, start_time);
+ /*
+ * Report on elapsed time and CPU usage. Depending what
+ * performance issue you're chasing down, different values may be
+ * of particular interest, so report all the info we've got.
+ */
+ printf ("Overall run time with %d threads = %Lfs, %Lfms per iteration.\n",
+ n_threads, wallclock, 1000 * wallclock / iter_count);
+ user = tvsub (finish.ru_utime, start.ru_utime);
+ sys = tvsub (finish.ru_stime, start.ru_stime);
+ total = user + sys;
+ printf ("CPU usage: user=%Lfs sys=%Lfs total=%Lfs.\n", user, sys, total);
+ printf ("Utilization: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n",
+ 100 * user / wallclock,
+ 100 * sys / wallclock,
+ 100 * total / wallclock);
+ printf ("Util/thread: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n",
+ 100 * user / wallclock / n_threads,
+ 100 * sys / wallclock / n_threads,
+ 100 * total / wallclock / n_threads);
+ printf ("Total CPU use per iteration per thread: %Lfms\n",
+ 1000 * total / n_threads / iter_count);
+ return 0;
+}
More information about the cvs-krb5
mailing list