//(C) João Carlos Ferreira Gonçalves / CK / C3R14L.K1L4
//17-02-2009
public class HighResolutionTime {
	static {
		System.loadLibrary("HighResolutionTime");
	}

	/**
	 * Tries to get the getRDTSC function execution time (in cycles).
	 * 
	 * @param iterations
	 * @return
	 */
	public static long getMinimumTSCDifference(int iterations) {
		System.out.println("computing minimum TSC difference for " + iterations + " iterations");
		long tsc1, tsc0, tsc_d;
		long min_dif = Long.MAX_VALUE;
		for (int i = 0; i < iterations; i++) {
			tsc0 = getRDTSC();
			tsc1 = getRDTSC();
			tsc_d = tsc1 - tsc0;
			if (tsc_d < min_dif && tsc_d > 0) {
				min_dif = tsc_d;
			}
		}
		return min_dif;
	}

	/**
	 * Reads from the CPU the time stamp counter. Returns the TSC value in an signed long, so watch out for wrapping (sign). Does not guarantee to
	 * execute in a specific processor on multi-CPU systems. Seems to take a minimum of 30 cycles but depending on the CPU and internal
	 * architecture/optimizations (like out-of-order execution) this value can change.
	 * 
	 * @return The time stamp counter as an signed long.
	 */
	public static native long getRDTSC();

	/**
	 * A demo function measuring TSC difference between intervals of one second.
	 * 
	 * @param seconds
	 */
	public static void showTSCDifferencePerSecond(int seconds) {
		for (int i = 0; i < seconds; i++) {
			long tsc0 = getRDTSC() - 30;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long tsc1 = getRDTSC() - 30;
			System.out.println(tsc1 - tsc0);
		}
	}

	public static void main(String[] args) {
		showTSCDifferencePerSecond(Integer.parseInt(args[0]));
		System.out.println(getMinimumTSCDifference(Integer.parseInt(args[1])));
	}

	/**
	 * Queries the performance counter. According to the MSDN documentation, "The QueryPerformanceCounter function retrieves the current value of the
	 * high-resolution performance counter". Seems to take a minimum of 1.6 us.
	 * 
	 * @return
	 */
	public static native long QueryPerformanceCounter();

	/**
	 * Queries the performance counter frequency. According to the MSDN documentation,"The QueryPerformanceFrequency function retrieves the frequency of the high-resolution performance counter, if one exists. The frequency cannot change while the system is running"
	 * . Seems to take a minimum of 1.6 us.
	 * 
	 * @return
	 */
	public static native long QueryPerformanceFrequency();
}
