summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-10-23 18:14:55 +0000
committerTavian Barnes <tavianator@gmail.com>2009-10-23 18:14:55 +0000
commit35a1d0d051546f0bbaae9338aa3fed4d04a9a92e (patch)
tree3c7f63ca40df5f155b564e40cf13859bdefe5ad6
parent18068cf26d34d28db8c70e26930cd842c3aecfb4 (diff)
downloadlibsandglass-35a1d0d051546f0bbaae9338aa3fed4d04a9a92e.tar.xz
New sandglass_bench_* macros, remove SANDGLASS_REALTICKS.
sandglass_bench_fine() replaces SANDGLASS_REALTICKS; use SANDGLASS_CPUTIME instead. Also, sandglass_bench_noprecache() for when the expression to be timed has side-effects and should be executed only once.
-rw-r--r--src/sandglass.c20
-rw-r--r--src/sandglass.h68
-rw-r--r--tests/monotonic-realticks.c4
-rwxr-xr-xtests/simple-test148
4 files changed, 59 insertions, 181 deletions
diff --git a/src/sandglass.c b/src/sandglass.c
index 6db28a3..f97b9c1 100644
--- a/src/sandglass.c
+++ b/src/sandglass.c
@@ -104,19 +104,10 @@ sandglass_real_create(sandglass_t *sandglass,
switch (attr->incrementation) {
case SANDGLASS_MONOTONIC:
switch (attr->resolution) {
- case SANDGLASS_REALTICKS:
-#ifdef SANDGLASS_TSC
- sandglass->resolution = sandglass_tsc_resolution();
- sandglass->loops = sandglass_tsc_loops();
- break;
-#else
- return -1;
-#endif
-
case SANDGLASS_CPUTIME:
#ifdef SANDGLASS_TSC
sandglass->resolution = sandglass_tsc_resolution();
- sandglass->loops = 1;
+ sandglass->loops = sandglass_tsc_loops();
break;
#else
return -1;
@@ -134,10 +125,6 @@ sandglass_real_create(sandglass_t *sandglass,
case SANDGLASS_INTROSPECTIVE:
switch (attr->resolution) {
- case SANDGLASS_REALTICKS:
- /* No such thing as an introspective raw TSC */
- return -1;
-
case SANDGLASS_CPUTIME:
if (sysconf(_SC_THREAD_CPUTIME) > 0 || sysconf(_SC_CPUTIME) > 0) {
sandglass->resolution = 1e9;
@@ -202,7 +189,6 @@ sandglass_real_gettime(sandglass_t *sandglass)
switch (sandglass->attributes.incrementation) {
case SANDGLASS_MONOTONIC:
switch (sandglass->attributes.resolution) {
- case SANDGLASS_REALTICKS:
case SANDGLASS_CPUTIME:
#ifdef SANDGLASS_TSC
sandglass->grains = sandglass_get_tsc();
@@ -230,10 +216,6 @@ sandglass_real_gettime(sandglass_t *sandglass)
case SANDGLASS_INTROSPECTIVE:
switch (sandglass->attributes.resolution) {
- case SANDGLASS_REALTICKS:
- /* No such thing as an introspective raw TSC */
- return -1;
-
case SANDGLASS_CPUTIME:
if (sysconf(_SC_THREAD_CPUTIME) > 0) {
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0)
diff --git a/src/sandglass.h b/src/sandglass.h
index 0d5e5e5..34461ba 100644
--- a/src/sandglass.h
+++ b/src/sandglass.h
@@ -26,6 +26,8 @@
#ifndef SANDGLASS_H_INCLUDED
#define SANDGLASS_H_INCLUDED
+#include <assert.h>
+
#ifdef __cplusplus
/* We've been included from a C++ file; mark everything here as extern "C" */
extern "C" {
@@ -65,14 +67,7 @@ enum sandglass_resolution_t
* portable. Uses the CLOCK_THREAD_CPUTIME_ID clock for
* SANDGLASS_INTROSPECTIVE mode, and the raw TSC for SANDGLASS_MONOTONIC.
*/
- SANDGLASS_CPUTIME,
-
- /*
- * Get timing information accurate to within one CPU clock cycle - requires
- * some looping and other trickery to account for TSCs which are not accurate
- * to within one clock cycle. Not valid with SANDGLASS_INTROSPECTIVE.
- */
- SANDGLASS_REALTICKS
+ SANDGLASS_CPUTIME
};
typedef enum sandglass_resolution_t sandglass_resolution_t;
@@ -134,16 +129,18 @@ int sandglass_elapse(sandglass_t *sandglass);
#define SANDGLASS_NO_UNROLL() __asm__ __volatile__ ("")
/*
- * Macro to facilitate correct benchmarking of blocks of code. May be called
+ * Macros to facilitate correct benchmarking of blocks of code. May be called
* like so:
- * sandglass_bench(&sandglass, f(x))
+ * sandglass_bench*(&sandglass, f(x))
* or like so:
- * sandglass_bench(&sandglass, {
+ * sandglass_bench*(&sandglass, {
* f(x);
* g(x);
* });
*/
-#define sandglass_bench(sandglass, routine) \
+
+/* Provides single clock cycle resolution in some cases */
+#define sandglass_bench_fine(sandglass, routine) \
do { \
/* Warm up the cache for these functions */ \
sandglass_begin(sandglass); \
@@ -161,6 +158,7 @@ int sandglass_elapse(sandglass_t *sandglass);
\
/* Warm up the cache for our routine */ \
routine; \
+ \
/* Time our routine in a loop */ \
sandglass_begin(sandglass); \
for ((sandglass)->i = 0; \
@@ -168,6 +166,7 @@ int sandglass_elapse(sandglass_t *sandglass);
++(sandglass)->i) { \
SANDGLASS_NO_UNROLL(); \
routine; \
+ SANDGLASS_NO_UNROLL(); \
} \
sandglass_elapse(sandglass); \
\
@@ -176,6 +175,51 @@ int sandglass_elapse(sandglass_t *sandglass);
(sandglass)->grains /= (sandglass)->loops; \
} while (0)
+/* General high resolution timer */
+#define sandglass_bench(sandglass, routine) \
+ do { \
+ /* Warm up the cache for these functions */ \
+ sandglass_begin(sandglass); \
+ sandglass_elapse(sandglass); \
+ \
+ /* Time an empty routine for our baseline */ \
+ sandglass_begin(sandglass); \
+ sandglass_elapse(sandglass); \
+ (sandglass)->baseline = (sandglass)->grains; \
+ \
+ /* Warm up the cache for our routine */ \
+ routine; \
+ \
+ /* Time the routine */ \
+ sandglass_begin(sandglass); \
+ routine; \
+ sandglass_elapse(sandglass); \
+ \
+ /* Subtract the baseline */ \
+ (sandglass)->grains -= (sandglass)->baseline; \
+ } while (0)
+
+/* Only executes routine once - useful if routine has side-effects */
+#define sandglass_bench_noprecache(sandglass, routine) \
+ do { \
+ /* Warm up the cache for these functions */ \
+ sandglass_begin(sandglass); \
+ sandglass_elapse(sandglass); \
+ \
+ /* Time an empty loop for our baseline */ \
+ sandglass_begin(sandglass); \
+ sandglass_elapse(sandglass); \
+ (sandglass)->baseline = (sandglass)->grains; \
+ \
+ /* Time the routine */ \
+ sandglass_begin(sandglass); \
+ routine; \
+ sandglass_elapse(sandglass); \
+ \
+ /* Subtract the baseline */ \
+ (sandglass)->grains -= (sandglass)->baseline; \
+ } while (0)
+
#ifdef __cplusplus
}
#endif
diff --git a/tests/monotonic-realticks.c b/tests/monotonic-realticks.c
index 9b5daff..51404f5 100644
--- a/tests/monotonic-realticks.c
+++ b/tests/monotonic-realticks.c
@@ -30,14 +30,14 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_REALTICKS };
+ sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_CPUTIME };
if (sandglass_create(&sandglass, &attr, &attr) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
- sandglass_bench(&sandglass, sandglass_get_tsc());
+ sandglass_bench_fine(&sandglass, sandglass_get_tsc());
printf("%ld\n", sandglass.grains);
diff --git a/tests/simple-test b/tests/simple-test
deleted file mode 100755
index 8fbcf16..0000000
--- a/tests/simple-test
+++ /dev/null
@@ -1,148 +0,0 @@
-#! /bin/sh
-
-# simple-test - temporary wrapper script for .libs/simple-test
-# Generated by ltmain.sh (GNU libtool) 2.2.6
-#
-# The simple-test program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='/bin/sed -e 1s/^X//'
-sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-relink_command="(cd /home/tavianator/libsandglass/tests; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/bin:/usr/bin:/sbin:/usr/sbin:/opt/java/bin:/opt/java/jre/bin:/home/tavianator/bin:/usr/bin/perlbin/site:/usr/bin/perlbin/vendor:/usr/bin/perlbin/core:/opt/qt/bin; export PATH; gcc -g -Wall -o \$progdir/\$file simple.o ../src/.libs/libsandglass.so -lrt -Wl,-rpath -Wl,/home/tavianator/libsandglass/src/.libs)"
-
-# This environment variable determines our operation mode.
-if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
- # install mode needs the following variables:
- generated_by_libtool_version='2.2.6'
- notinst_deplibs=' ../src/libsandglass.la'
-else
- # When we are sourced in execute mode, $file and $ECHO are already set.
- if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
- ECHO="echo"
- file="$0"
- # Make sure echo works.
- if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
- # Yippee, $ECHO works!
- :
- else
- # Restart under the correct shell, and then maybe $ECHO will work.
- exec /bin/sh "$0" --no-reexec ${1+"$@"}
- fi
- fi
-
- # Find the directory that this script lives in.
- thisdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "x$thisdir" = "x$file" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
- while test -n "$file"; do
- destdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
-
- # If there was a directory component, then change thisdir.
- if test "x$destdir" != "x$file"; then
- case "$destdir" in
- [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
- *) thisdir="$thisdir/$destdir" ;;
- esac
- fi
-
- file=`$ECHO "X$file" | $Xsed -e 's%^.*/%%'`
- file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
- done
-
-
- # Usually 'no', except on cygwin/mingw when embedded into
- # the cwrapper.
- WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
- if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
- # special case for '.'
- if test "$thisdir" = "."; then
- thisdir=`pwd`
- fi
- # remove .libs from thisdir
- case "$thisdir" in
- *[\\/].libs ) thisdir=`$ECHO "X$thisdir" | $Xsed -e 's%[\\/][^\\/]*$%%'` ;;
- .libs ) thisdir=. ;;
- esac
- fi
-
- # Try to get the absolute directory name.
- absdir=`cd "$thisdir" && pwd`
- test -n "$absdir" && thisdir="$absdir"
-
- program=lt-'simple-test'
- progdir="$thisdir/.libs"
-
- if test ! -f "$progdir/$program" ||
- { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
- test "X$file" != "X$progdir/$program"; }; then
-
- file="$$-$program"
-
- if test ! -d "$progdir"; then
- mkdir "$progdir"
- else
- rm -f "$progdir/$file"
- fi
-
- # relink executable if necessary
- if test -n "$relink_command"; then
- if relink_command_output=`eval $relink_command 2>&1`; then :
- else
- echo "$relink_command_output" >&2
- rm -f "$progdir/$file"
- exit 1
- fi
- fi
-
- mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
- { rm -f "$progdir/$program";
- mv -f "$progdir/$file" "$progdir/$program"; }
- rm -f "$progdir/$file"
- fi
-
- if test -f "$progdir/$program"; then
- if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
- # Run the actual program with our arguments.
-
- exec "$progdir/$program" ${1+"$@"}
-
- $ECHO "$0: cannot exec $program $*" 1>&2
- exit 1
- fi
- else
- # The program doesn't exist.
- $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
- $ECHO "This script is just a wrapper for $program." 1>&2
- echo "See the libtool documentation for more information." 1>&2
- exit 1
- fi
-fi