From e2d0f5d9c38561d67f23754c00addb4a3547efb2 Mon Sep 17 00:00:00 2001 From: Stiver Date: Tue, 4 Mar 2014 15:13:11 +0100 Subject: initial commit --- timer/HRTimerResolution.java | 68 ++++++++++++++++++++ timer/SystemTimerResolution.java | 31 +++++++++ timer/com/vladium/utils/timing/ITimer.java | 54 ++++++++++++++++ .../com/vladium/utils/timing/ITimerConstants.java | 31 +++++++++ .../com/vladium/utils/timing/JavaSystemTimer.java | 74 ++++++++++++++++++++++ timer/com/vladium/utils/timing/TimerFactory.java | 74 ++++++++++++++++++++++ timer/native/com_vladium_utils_timing_HRTimer.c | 71 +++++++++++++++++++++ timer/native/com_vladium_utils_timing_HRTimer.h | 22 +++++++ 8 files changed, 425 insertions(+) create mode 100644 timer/HRTimerResolution.java create mode 100644 timer/SystemTimerResolution.java create mode 100644 timer/com/vladium/utils/timing/ITimer.java create mode 100644 timer/com/vladium/utils/timing/ITimerConstants.java create mode 100644 timer/com/vladium/utils/timing/JavaSystemTimer.java create mode 100644 timer/com/vladium/utils/timing/TimerFactory.java create mode 100644 timer/native/com_vladium_utils_timing_HRTimer.c create mode 100644 timer/native/com_vladium_utils_timing_HRTimer.h (limited to 'timer') diff --git a/timer/HRTimerResolution.java b/timer/HRTimerResolution.java new file mode 100644 index 0000000..318694f --- /dev/null +++ b/timer/HRTimerResolution.java @@ -0,0 +1,68 @@ +import java.text.DecimalFormat; + +import com.vladium.utils.timing.ITimer; +import com.vladium.utils.timing.TimerFactory; + +// ---------------------------------------------------------------------------- +/** + * A demo class to show off the higher resolution available from HRTimer class + * and to investigate the resolution offered by Java "time-related" + * methods other than System.currentTimeMillis().

+ * + * Make sure that hrtlib.dll JNI lib is in java.library.path or TimerFactory + * will fall back to the Java system timer: + *

+ *  >java -Djava.library.path=(dir containing hrtlib.dll) HRTimerResolution
+ * 
+ * + * @author (C) Vlad Roubtsov, 2002 + */ +public class HRTimerResolution +{ + // public: ................................................................ + + public static void main (final String [] args) throws Exception + { + final DecimalFormat format = new DecimalFormat (); + format.setMinimumFractionDigits (3); + format.setMaximumFractionDigits (3); + + // create an ITimer using the Factory class: + final ITimer timer = TimerFactory.newTimer (); + + // JIT/hotspot warmup: + for (int i = 0; i < 3000; ++ i) + { + timer.start (); + timer.stop (); + timer.getDuration (); + timer.reset (); + } + + final Object lock = new Object (); // this is used by monitor.wait() below + + for (int i = 0; i < 5; ++ i) + { + timer.start (); + + // uncomment various lines below to see the resolution + // offered by other Java time-related methods; with all + // lines commented out this loop reports time elapsed + // between successive calls to t.start() and t.stop(), thus + // providing an estimate for timer's raw resolution + + synchronized (lock) { lock.wait (1); } + //Thread.currentThread ().sleep (1); + //Thread.currentThread ().sleep (0, 500); + //Thread.currentThread ().join (1); + + timer.stop (); + + System.out.println ("duration = " + + format.format (timer.getDuration ()) + " ms"); + timer.reset (); + } + } + +} // end of class +// ---------------------------------------------------------------------------- diff --git a/timer/SystemTimerResolution.java b/timer/SystemTimerResolution.java new file mode 100644 index 0000000..56ececd --- /dev/null +++ b/timer/SystemTimerResolution.java @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +/** + * A simple class to see what the Java system timer resolution is on your + * system. + * + * @author (C) Vlad Roubtsov, 2002 + */ +public class SystemTimerResolution +{ + // public: ................................................................ + + public static void main (final String [] args) + { + // JIT/hotspot warmup: + for (int r = 0; r < 3000; ++ r) System.currentTimeMillis (); + + long time = System.currentTimeMillis (), time_prev = time; + + for (int i = 0; i < 5; ++ i) + { + // busy wait until system time changes: + while (time == time_prev) + time = System.currentTimeMillis (); + + System.out.println ("delta = " + (time - time_prev) + " ms"); + time_prev = time; + } + } + +} // end of class +// ---------------------------------------------------------------------------- diff --git a/timer/com/vladium/utils/timing/ITimer.java b/timer/com/vladium/utils/timing/ITimer.java new file mode 100644 index 0000000..98029b1 --- /dev/null +++ b/timer/com/vladium/utils/timing/ITimer.java @@ -0,0 +1,54 @@ + +package com.vladium.utils.timing; + +// ---------------------------------------------------------------------------- +/** + * A simple interface for measuring time intervals. An instance of this goes + * through the following lifecycle states: + *
+ *
ready + *
timer is ready to start a new measurement + *
started + *
timer has recorded the starting time interval point + *
stopped + *
timer has recorded the ending time interval point + *
+ * See individual methods for details.

+ * + * If this library has been compiled with {@link ITimerConstants#DO_STATE_CHECKS} + * set to 'true' the implementation will enforce this lifecycle model and throw + * IllegalStateException when it is violated. + * + * @author (C) Vlad Roubtsov, 2002 + */ +public interface ITimer +{ + // public: ................................................................ + + /** + * Starts a new time interval and advances this timer instance to 'started' + * state. This method can be called from 'ready' state only. */ + void start (); + + /** + * Terminates the current time interval and advances this timer instance to + * 'stopped' state. Interval duration will be available via + * {@link #getDuration()} method. This method can be called from 'started' + * state only. */ + void stop (); + + /** + * Returns the duration of the time interval that elapsed between the last + * calls to {@link #start()} and {@link #stop()}. This method can be called + * any number of times from 'stopped' state and will return the same value + * each time.

+ * * @return interval duration in milliseconds */ + double getDuration (); + + /** + * This method can be called from any state and will reset this timer + * instance back to 'ready' state. */ + void reset (); + +} // end of interface +// ---------------------------------------------------------------------------- diff --git a/timer/com/vladium/utils/timing/ITimerConstants.java b/timer/com/vladium/utils/timing/ITimerConstants.java new file mode 100644 index 0000000..29435ae --- /dev/null +++ b/timer/com/vladium/utils/timing/ITimerConstants.java @@ -0,0 +1,31 @@ + +package com.vladium.utils.timing; + +// ---------------------------------------------------------------------------- +/** + * A package-private collection of constants used by {@link ITimer} implementations + * in HRTimer and JavaSystemTimer classes. + * + * @author (C) Vlad Roubtsov, 2002 + */ +interface ITimerConstants +{ + // public: ................................................................ + + /** + * Conditional compilation flag to enable/disable state checking in timer + * implementations. Just about the only reason you might want to disable + * this is to reduce the timer overhead, but in practice the gain is very + * small. */ + static final boolean DO_STATE_CHECKS = true; + + /** + * Timer state enumeration. */ + static final int STATE_READY = 0, STATE_STARTED = 1, STATE_STOPPED = 2; + + /** + * User-friendly timer state names indexed by their state values. */ + static final String [] STATE_NAMES = {"READY", "STARTED", "STOPPED"}; + +} // end of interface +// ---------------------------------------------------------------------------- diff --git a/timer/com/vladium/utils/timing/JavaSystemTimer.java b/timer/com/vladium/utils/timing/JavaSystemTimer.java new file mode 100644 index 0000000..e3f3b48 --- /dev/null +++ b/timer/com/vladium/utils/timing/JavaSystemTimer.java @@ -0,0 +1,74 @@ + +package com.vladium.utils.timing; + +// ---------------------------------------------------------------------------- +/** + * A package-private implementation of {@link ITimer} based around Java system + * timer [System.currentTimeMillis() method]. It is used when + * HRTimer implementation is unavailable.

+ * + * {@link TimerFactory} acts as the Factory for this class.

+ * + * MT-safety: an instance of this class is safe to be used within the same + * thread only. + * + * @author (C) Vlad Roubtsov, 2002 + */ +final class JavaSystemTimer implements ITimer, ITimerConstants +{ + // public: ................................................................ + + public void start () + { + if (DO_STATE_CHECKS) + { + if (m_state != STATE_READY) + throw new IllegalStateException (this + ": start() must be called from READY state, current state is " + STATE_NAMES [m_state]); + } + + if (DO_STATE_CHECKS) m_state = STATE_STARTED; + m_data = System.currentTimeMillis (); + } + + public void stop () + { + // latch stop time in a local var before doing anything else: + final long data = System.currentTimeMillis (); + + if (DO_STATE_CHECKS) + { + if (m_state != STATE_STARTED) + throw new IllegalStateException (this + ": stop() must be called from STARTED state, current state is " + STATE_NAMES [m_state]); + } + + m_data = data - m_data; + if (DO_STATE_CHECKS) m_state = STATE_STOPPED; + } + + public double getDuration () + { + if (DO_STATE_CHECKS) + { + if (m_state != STATE_STOPPED) + throw new IllegalStateException (this + ": getDuration() must be called from STOPPED state, current state is " + STATE_NAMES [m_state]); + } + + return m_data; + } + + public void reset () + { + if (DO_STATE_CHECKS) m_state = STATE_READY; + } + + // protected: ............................................................. + + // package: ............................................................... + + // private: ............................................................... + + private int m_state; // used to keep track of timer state + private long m_data; // timing data + +} // end of class +// ---------------------------------------------------------------------------- diff --git a/timer/com/vladium/utils/timing/TimerFactory.java b/timer/com/vladium/utils/timing/TimerFactory.java new file mode 100644 index 0000000..ae127c5 --- /dev/null +++ b/timer/com/vladium/utils/timing/TimerFactory.java @@ -0,0 +1,74 @@ + +package com.vladium.utils.timing; + +// ---------------------------------------------------------------------------- +/** + * This non-instantiable non-extendible class acts as a Factory for {@link ITimer} + * implementations. + * + * @author (C) Vlad Roubtsov, 2002 + */ +public abstract class TimerFactory +{ + // public: ................................................................ + + private static final String HRTIMER_LIB = "hrtlib"; + + /** + * Creates a new instance of {@link ITimer} which is returned in 'ready' + * state. If the JNI-based/high-resolution implementation is not available + * this will return an instance of JavaSystemTimer, so this + * method is guaranteed not to fail. + * + * @return ITimer a new timer instance in 'ready' state [never null] */ + + public static void initialize(String path) { + + UnsatisfiedLinkError exception = null; + + try { + System.loadLibrary (HRTIMER_LIB); + } catch (UnsatisfiedLinkError e) { + if(path != null) { + try { + System.load(path); + } catch (UnsatisfiedLinkError ex) { + exception = ex; + } + } else { + exception = e; + } + } + + if(exception != null) { + System.out.println ("native lib '" + HRTIMER_LIB + + "' not found in 'java.library.path': " + + System.getProperty ("java.library.path") + +path==null?"":(" or in "+path)); + + throw exception; // re-throw + } + } + + public static ITimer newTimer () + { +// try +// { + return new HRTimer (); +// } +// catch (Throwable t) +// { +// return new JavaSystemTimer (); +// } + } + + // protected: ............................................................. + + // package: ............................................................... + + // private: ............................................................... + + private TimerFactory () {} // prevent subclassing + +} // end of class +// ---------------------------------------------------------------------------- diff --git a/timer/native/com_vladium_utils_timing_HRTimer.c b/timer/native/com_vladium_utils_timing_HRTimer.c new file mode 100644 index 0000000..647837d --- /dev/null +++ b/timer/native/com_vladium_utils_timing_HRTimer.c @@ -0,0 +1,71 @@ +/* ------------------------------------------------------------------------- */ +/* + * A win32 implementation of JNI methods in com.vladium.utils.timing.HRTimer + * class. The author compiled it using Microsoft Visual C++ but the code + * should be easy to use with any compiler for win32 platform. + * + * For simplicity, this implementaion assumes JNI 1.2+ and omits error handling. + * + * (C) 2002, Vladimir Roubtsov [vroubtsov@illinoisalumni.org] + */ +/* ------------------------------------------------------------------------- */ + +#if !defined NDEBUG +#include +#endif // NDEBUG + +#include + +#include "com_vladium_utils_timing_HRTimer.h" + +// scale factor for converting a performancce counter reading into milliseconds: +static jdouble s_scaleFactor; + +/* ------------------------------------------------------------------------- */ + +/* + * This method was added in JNI 1.2. It is executed once before any other + * methods are called and is ostensibly for negotiating JNI spec versions, but + * can also be conveniently used for initializing variables that will not + * change throughout the lifetime of this process. + */ +JNIEXPORT jint JNICALL +JNI_OnLoad (JavaVM * vm, void * reserved) +{ + LARGE_INTEGER counterFrequency; + + QueryPerformanceFrequency (& counterFrequency); + + // NOTE: counterFrequency will be zero for a machine that does not have + // support for a high-resolution counter. This is only likely for very + // old hardware but for a robust implementation you should handle this + // case. + +#if !defined NDEBUG + printf ("PCFrequency called: %I64d\n", counterFrequency.QuadPart); +#endif + + s_scaleFactor = counterFrequency.QuadPart / 1000.0; + + + return JNI_VERSION_1_2; +} +/* ......................................................................... */ + +/* + * Class: com_vladium_utils_timing_HRTimer + * Method: getTime + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL +Java_com_vladium_utils_timing_HRTimer_getTime (JNIEnv * e, jclass cls) +{ + LARGE_INTEGER counterReading; + + QueryPerformanceCounter (& counterReading); + + return counterReading.QuadPart / s_scaleFactor; +} + +/* ------------------------------------------------------------------------- */ +/* end of file */ diff --git a/timer/native/com_vladium_utils_timing_HRTimer.h b/timer/native/com_vladium_utils_timing_HRTimer.h new file mode 100644 index 0000000..357db0d --- /dev/null +++ b/timer/native/com_vladium_utils_timing_HRTimer.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_vladium_utils_timing_HRTimer */ + +#ifndef _Included_com_vladium_utils_timing_HRTimer +#define _Included_com_vladium_utils_timing_HRTimer +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: com_vladium_utils_timing_HRTimer + * Method: getTime + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL +Java_com_vladium_utils_timing_HRTimer_getTime (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.2.3