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