High Resolution Timer in Java 1.4.2

There is a “hidden” high resolution timer in J2SE 1.4.2, here is an example timer class how to use it:

import sun.misc.Perf;

public class HiResTimer {
Perf hiResTimer;
long freq;

public HiResTimer() {
hiResTimer = Perf.getPerf();
freq = hiResTimer.highResFrequency();
}

public long currentTimeMillis() {
return hiResTimer.highResCounter() * 1000 / freq;
}
}

and here is a little example program for measuring the accuracy of the class above:

public class TimerTest {
public static void main(String[] args) {
long start, stop;
HiResTimer testTimer = new HiResTimer();
start = testTimer.currentTimeMillis();
while(testTimer.currentTimeMillis() == start);
stop = testTimer.currentTimeMillis();
System.out.println(“Time: “+(stop-start)+” ms”);
}
}

With Windows XP I got 1 ms accuracy. With a similar test program I got 10 ms accuracy for System.currentTimeMillis(). At least with WinXP the “hidden” timer actually gives a much better accuracy than 1 ms, I guess it uses the same Windows timer as Java3D high resolution timer. The freq parameter with my WinXP setup is 3579545 ticks / second. I haven’t tested it with other operating systems (Linux/Solaris/Win2000/Win98…). If someone is using any of those operating systems, please post the accuracy to this forum…

Hey aikarele :smiley:

I’ve seen your 64k demo (varhaiset_signaalit) several months ago and was really impressed. It was the first demo I’ve seen wich was written in Java and it was able to run in fullscreen :o (I hadn’t known that it’s possible before).

Without your demo I won’t be here. Thank you for bringing me back to this wonderful language :slight_smile:

Gonna update my VM in some hours. I’ll drop the results (win98se) here.

Hm … not documented, may move or vanish with every new release. I hope the make it a public part of the API soon.

Edit: I tested it on some Linux/Athlon machine (don’t ask me about details)
:~> j2sdk1.4.2/bin/java TimerTest
Time: 1 ms

[quote] several months ago and was really impressed. It was the first demo I’ve seen wich was written in Java and it was able to run in fullscreen :o (I hadn’t known that it’s possible before).
[/quote]
Not to knock the demo, but this was possibly in java about a year ago (albeit buggy in the first 1.4 VMs). There was lots of experimentation and apps using it from people on the forum.

Is this a new timer? I would have thought it would be easier to move across the high res timer from j3d. Maybe its just a different wrapper around the same native code…

Yes… I know that :stuck_out_tongue:

I just had lost interest in Java ~2 years ago; therefore I wasn’t aware of the api changes, hadn’t checked any demo applications and didn’t visit any Java forum. Simply because I wasn’t interested.

Btw the demo (intro) was from assembly2002… so fullscreen was quite new to Java the days the demo was made.

Hi

first message on this board :slight_smile: glad i can post something usefull:

Here’s my Timing class (note the cast):

//------------------------------------------------------
import sun.misc.Perf;

public class PerfTimer {
Perf hiResTimer;
long freq;

  public PerfTimer() {
        hiResTimer = Perf.getPerf();
        freq = hiResTimer.highResFrequency();
  }
  
  public double getTime() {
        return (double)hiResTimer.highResCounter() * 1000 / (double)freq;
  }

}

//------------------------------------------------------

This is the Testing class:

//------------------------------------------------------
public class Test {
public static void main(String[] args) {
PerfTimer t = new PerfTimer();
double start, end, delta, sumOfDeltas, averagedelta;
int resTestIterations = 1000;

        System.out.println("Test1: measure a system-timed intervall");
        start = t.getTime();
        long sysstart = System.currentTimeMillis();
        long sysend;
        do { sysend = System.currentTimeMillis(); }
        while ( sysend < sysstart + 1000);
        end = t.getTime();
        long sysdelta = sysend-sysstart;
        delta = end-start;
        
        System.out.println("systimer-delta: "+sysdelta);
        System.out.println("perftimer-delta: "+delta);
        
        System.out.println("\nTest2: resolution");
        sumOfDeltas = 0;
        for (int i=0;i<resTestIterations;i++) {
              start = t.getTime();
              while (start == t.getTime());
              end = t.getTime();
              delta = end-start;
              sumOfDeltas += delta;
        }
        averagedelta = sumOfDeltas/resTestIterations;
        System.out.println("resolution: "+ delta);
        System.out.println("average resolution:"+ averagedelta);
        
        
        System.out.println("\nTest3: measure a perf-timed intervall with sys-timer");
        sysstart = System.currentTimeMillis();
        start = t.getTime();
        do end = t.getTime();
        while (end <start+1000); 
        sysend = System.currentTimeMillis();
        delta = end-start;
        sysdelta = sysend-sysstart;
        System.out.println("Perf-delta:"+delta);
        System.out.println("system-Time-delta:"+sysdelta);
  }

}
//------------------------------------------------------

its quite long but i couldn’t believe the results first :slight_smile:

this is an example output (using Win98se)

Test1: measure a system-timed intervall
systimer-delta: 1040
perftimer-delta: 1002.6182135134682

Test2: resolution
resolution: 0.011733351212569687
average resolution:0.013178229604925037

Test3: measure a perf-timed intervall with sys-timer
Perf-delta:1000.3126100001673
system-Time-delta:980

so this timer actually seems to have ~12E-6 second resolution (is that 12 nanos in english or 12mycro?)

the differences between perf and sys timing are always inside the 50ms-accuracy of the system-timer.

the average resolution goes up and down a bit betweend differnt tests but usually just around 0.002 millis.

lets hope sun has a heart for gamers and leaves this timer!

oNyx, thanks for your nice feedback. We are going to release even better Java stuff this year, so stay tuned :wink:

Themroc, yes it could vanish any time. But Florian Bomers (the guy responsible for Java Sound at Sun) is going to use it in Tritonus’ Java sequencer, so I guess at least he is not expecting it to vanish soon. I guess they could not make it an “official” timer class in J2SE 1.4.2, because it would have been a new feature, but I hope it will be an official class in J2SE 1.5.

Orangy Tang, our demo (actually a 64 kB intro) was released almost a year ago, and we made it using J2SE 1.4.0 beta. So although it was not made to demonstrate fullscreen API, it definitely was made with the first possible Java SDK that had fullscreen API support ;). And to my great surprise, it actually works BETTER with 1.4.0 than 1.4.1 or 1.4.2. About the timers; my guess is that both the Windows implementation of the “new” timer and J3D timer (and several native timers floating in the web) use QueryPerformanceCounter and QueryPerformanceFrequency functions.

Smoke, you can actually get the resolution of the timer with hiResTimer.highResFrequency() method ;). Resolution on my WinXP set up is 3579545 ticks/sec, which means a resolution of 1/3579545 = 0.000000279365114840015 s.

Those of you who wonder what is varhaiset signaalit, you can download it from here:
http://www.pouet.net/prod.php?which=7145

Hey how did you save you images for the demo?

Read the introFAQ.txt ;). We developed image compression algorithms that allowed us to save the images in 640x480 resolution using about 1.5 kB per image.

Using a slight different test on my 3.06GHz XP machine I obtained the following

HiRes counter frequency: 3.0496E9
Mean counter call: 628.34E-9s

On dual processor machines the Windows QueryPerformanceCounter api uses the processor clock counter. This could lead to unexpected results when the processor slows down due to overheating.


import sun.misc.Perf;
import java.text.DecimalFormat;

class TestPerformance
{
      public static void main(String[] args)
      {
            Perf p = Perf.getPerf();
            long freq = p.highResFrequency();
            DecimalFormat engFormat = new DecimalFormat("##0.##E0");
            System.out.println("HiRes counter frequency: "+engFormat.format(freq));
            System.out.println("Performance class: "+p.getClass());
            
            for (int i=1; i<20; i++)
            {
                  int n=500;
                  long t=0;
                  for (int j=0; j<n; j++)
                  {
                        long t0=p.highResCounter();
                        t += p.highResCounter()-t0;
                  }
                  System.out.println("Mean counter call: "+engFormat.format(t/(n*(float)freq))+"s");
            }
      }
}

If you are worried about those classes disappearing/moving you coudl dynamically load them. If they aren’t available default to System.currentTimeMillis().

e.g.



public interface Timer {
    public long currentTimeMillis();
}

public class HiResTimer implements Timer {
    Perf hiResTimer; 
    long freq; 
 
    public HiResTimer() { 
        hiResTimer = Perf.getPerf(); 
        freq = hiResTimer.highResFrequency(); 
    }
 
    public long currentTimeMillis() { 
        return hiResTimer.highResCounter() * 1000 / freq; 
    } 

}

public class StdTimer implements Timer {
    public long currentTimeMillis() {
        return System.currentTimeMillis();
    }
}

Then when making a timer:


Timer timer = null;
try {
    Class timerClass = Class.forName( "HiResTimer" );
    timer = (Timer)timerClass.newInstance();
}
catch( Throwable t ) {
    // if we fail to make a hi-res timer
    timer = new StdTimer();
}

Yep, if you use the hires timer, you definitely need a fallback in case it is not available. But I think it would be nicer if the availability of the hires timer is checked by the Timer class itself, not the caller. For example, the code could be something like this:

Then the caller could use the Timer like this:


   Timer timer = new Timer();
   long time = timer.currentTimeMillis();

However that makes compilation more tricky.

Tricky? Because you need a Java version that supports hires timer (i.e. J2SE 1.4.2 at the moment) to compile it? Why on earth would you have hires fallback timer if you are not using such a compiler? :wink:

Besides, your code will not compile with any Java version because “import sun.misc.Perf;” is missing ;D

[edit: sorry, of course your code will compile without the import unless the hires timer is needed]

Sorry, I would have explained more, but I had visitors arrive, then the forum moved (and the PC I am using for the net has been misbehaving badly).

Yep. That’s what I meant, you can simply ignore/delete the HiResTimer class if it won’t compile, rather than having to wade in and alter source code.

p.s. I think that this kind of thing is one of the coolest features of java. It lets you dynamically exploit whatever features are available on the host, but still function on other systems with those features missing. Shame it’s a bit fiddly. It would be really good if the reflection/introspection stuff was somehow more “builtin” mkaing it easier to use. But then I guess it’d make it easier to abuse too :wink:

I believe this functionality is committed for 1.5
I suspect this is an early version to get the bugs out.

If its released as part of the 1.5 fromal release it will have a real (not Sun specific) package name.

JK

[quote]I’ve seen your 64k demo (varhaiset_signaalit) several months ago and was really impressed. It was the first demo I’ve seen wich was written in Java and it was able to run in fullscreen (I hadn’t known that it’s possible before).

Without your demo I won’t be here. Thank you for bringing me back to this wonderful language
[/quote]
Well now we have released another 64 kB intro at Assembly 2003 called raskasmetallia, which uses the high resolution timer in Java 1.4.2 :wink:

Feel free to download it from:
http://www.pouet.net/prod.php?which=10585

Comments, feedback and especially bug reports are all welcome…