GAGE Engine Early Access

Hi guys. I know I’ve dropped a few hints over the last week about a really cool gaming engine I’ve been working on. Well, now I’m going to drop some code. A (rather austere) site has been set up for my engine, tentativaly named GAGE - Genuine Alternative Gaming Engine. Currently, the GAGETimer and GAGESound APIs are online for public review and consumption.

Please be aware that GAGESound is currently bare-bones and lacks a few features like volume contol. None the less, don’t let that stop you from checking it out and letting me know what you think! Also, could someone use the GAGETimer on an OSX system and find out the resolution? I believe that OSX should provide 1ms resolution, but I can’t be sure until someone trys it.

I’ll post here when new releases are available. Check it out at:

http://java.dnsalias.com

Mac OS X
getClockTicks()=0
getResolution()=9
getTicksPerSecond()=111

Not exactly what I was expecting… probably a rounding error and it should be resolution of 10?

[quote]Mac OS X
getClockTicks()=0
getResolution()=9
getTicksPerSecond()=111

Not exactly what I was expecting… probably a rounding error and it should be resolution of 10?
[/quote]
Errm… No, it finds the resolution through a hard loop that watches for the clock change. Did you run it more than once? (Just in case the JVM was starved for CPU)

uh… no I didn’t… I assumed the classes would be written to try to account for such variables with a long enough loop and averaging and jitter detection etc… Otherwise how are we supposed to use it if the results are so different every time??

E.g. here is the second run:

Mac OS X
getClockTicks()=0
getResolution()=16
getTicksPerSecond()=62

BIG DIFFERENCE, Let’s try again…

Mac OS X
getClockTicks()=0
getResolution()=5
getTicksPerSecond()=200

WHOA!

Me thinks this code needs some tweaking…

got the 5/200 result several times in a row now… ulp… now I got 6/166
A few more 5/200’s, a 6/166, oh a new one 4/250…

If possible those methods should be tweaked so they are more consistent… or at least document how they should be used to get an accurate result.

I should probably make it recalc more than once for accurate results. The problem seems to be in the JVM and classloader which is starving the thread that does the time figuring. As best I’ve been able to test, the routine works fine under the Sun VM, so I’m going to say that it’s probably a MacOSX specific issue. Glad I asked for testing. :slight_smile:

I’ll let you know when I have new code up.

How are you calculating resolution?

Are you exercising HotSpot enough to force it to compile the code? I’ve read that this requires at least 1000 calls to a method. How about something like:

// Error expected in measured elapsed time in nanoseconds
public long getResolution()
{
final byte NTIMES = 10;
long t1, t2;
long dt = 0L;

    // Warm up JIT/HotSpot compiler
  for (short s=0; s<3000; ++s)
        t1 = getCounter();

    for (byte b=0; b<NTIMES; ++b)
    {
        t1 = getCounter();
        t2 = getCounter();
        while (t1 == t2)
              t2 = getCounter();
        dt += (t2 - t1);
  }
      return dt/NTIMES;

}

  • Craig

Here’s the exact code (which is included in the download BTW):


static
{
    long time = System.currentTimeMillis();
    long prev_time = time;

    while(time == prev_time) time = System.currentTimeMillis();
            
    resolution = time-prev_time;
}

The concept is that this hard loop will note exactly when the timer changes and calculate the difference between the previous number and the current number. The problem is that it won’t work right if the thread is starved for time, say because the JVM is still loading in the background. Thus, I’m going to move the code out of a static clause and have it run inside the program thread. This may not solve the problem, but it’s a good start.

/me wonders why there isn’t a
System.getTimerResolution();
::slight_smile:

you should run that in a loop until the result returned is consistent for a few iterations.

Okay, a new version of the timer code is up. Let me know if it works any better.

And for everyone who’s been just dying to try it, the GAGE2D API is now available for download. It’s still in early stages, but it already covers more than just about any other 2D API I’ve ever used. Some existing features:

[] Any level Parallax map scrolling
[
] Automated collision detection of sprites
[*] Management of game “missles”

Features planned:

[] Arbitrary Collision Map support
[
] AI routines
[*] Other nifty features that people request! ;D

As always, the download contains full JavaDocs, example code, source, and JAR files.

Go get it at:

http://java.dnsalias.com

An example game that pulls all the APIs together, will be available as soon as I clean up my code. :wink:

Much better!

Now it consistently reports:

Mac OS X
getClockTicks()=0
getResolution()=1
getTicksPerSecond()=1000

Excellent! And Macs even manage to give a full 1000 ticks per second! I knew I liked those machines for a reason… :slight_smile:

Full JavaDocs for all APIs can now be viewed directly online. As usual, go to http://java.dnsalias.com and click on the JavaDocs link in the corner.

Excellent! And Macs even manage to give a full 1000 ticks per second!
I knew I liked those machines for a reason… :slight_smile:

My Mac OS X native C timer gives a resolution of about 1100 nanoseconds (1.1 microseconds = .0011 milliseconds).

When I use it in Java via JNI, the resolution is about 1500 nanoseconds, so I lose 300-400 nanoseconds going across the interface.

Note that your resolution algorithm does not adequately “warm up” HotSpot, so the code will not be forced to compile (it will be interpreted). When using System.currentTimeMillis() on the Mac this is not an issue since the apparent JVM timer resolution is 1 millisecond, but if you used a native timer you would obtain inconsistent results.

Are you planning to build in native timer support in future releases?

Craig

[quote]When I use it in Java via JNI, the resolution is about 1500 nanoseconds, so I lose 300-400 nanoseconds going across the interface.
[/quote]
Honestly, for the purpose of games, is the extra 300-400 nanoseconds that important? 1000 ticks per second should be more than enough to time a hundred or so frames per second.

[quote]Note that your resolution algorithm does not adequately “warm up” HotSpot, so the code will not be forced to compile (it will be interpreted). When using System.currentTimeMillis() on the Mac this is not an issue since the apparent JVM timer resolution is 1 millisecond, but if you used a native timer you would obtain inconsistent results.
[/quote]
I’m not quite sure what you mean here. If the HotSpot compiler doesn’t think it should be compiled, then there’s a good bet that it doesn’t need to be. SWPalmer has stated that he’s now receiving 1 ms resolution, so I’m not sure what the problem is. Do you get different results?

[quote]Are you planning to build in native timer support in future releases?
[/quote]
Well, I don’t have a Mac (yet), so I can’t create one. But if someone out there has the time and the need, I’d happily accept a donation. :slight_smile: All you need to do is to implement the NativeTimer interface and add your timer to be checked in the init() code of AdvancedTimer. You can look at the windows timer for an example.

Honestly, for the purpose of games, is the extra 300-400 nanoseconds
that important?

No, that was the difference between C resolution and Java resolution using my native timer.

1000 ticks per second should be more than enough to time a
hundred or so frames per second.

Good point, especially since the thread resolution is not very accurate. Perhaps a more experienced game programmer than I could coment?

1500 nanoseconds => 1/(1500 * 10^-9) = 666,666 ticks per second

I’m not quite sure what you mean here. If the HotSpot compiler
doesn’t think it should be compiled, then there’s a good bet that it
doesn’t need to be.

From what I’ve read, HotSpot compiles methods that are called more than 1,000 times or so. Calling a timer once (interpreted mode) will give you a much slower response (larger time resolution measurement) than calling it thousands of times (compiled mode) and averaging the results. I find a speedup in performance of 20x (interpreted/compiled ratio), which is significant.

Well, I don’t have a Mac (yet), so I can’t create one. But if someone out
there has the time and the need, I’d happily accept a donation. :slight_smile:

I’ll try this when I get some spare time.

Nice work!
Craig

— BEGIN ANNOUCEMENT —

The first demo of the complete API is online and it’s a side scrolling Shoot’em up. Go get it!

http://java.dnsalias.com

— END ANNOUCEMENT —

[quote] 1500 nanoseconds => 1/(1500 * 10^-9) = 666,666 ticks per second
[/quote]
Hmm… The evil timer! :stuck_out_tongue:

[quote] From what I’ve read, HotSpot compiles methods that are called more than 1,000 times or so. Calling a timer once (interpreted mode) will give you a much slower response (larger time resolution measurement) than calling it thousands of times (compiled mode) and averaging the results. I find a speedup in performance of 20x (interpreted/compiled ratio), which is significant.
[/quote]
It would be significant if the timer actually did anything. Since the interpreted vs. compiled difference for this code is about a few native instructions per method, warming up HotSpot won’t do much. The real problem with measuring the resolution was that the classloader ran in a low priority thread.

Thanks for your comments! :slight_smile:

For those that don’t want to figure out how to run it.

cd to the bin directory and type (for windows)

java -cp Shooter.jar;…\lib\gage2.jar;…\lib\Resources.jar;…\lib\sound.jar;…\lib\timer.jar Shooter

Or you could just run:

java -jar Shooter.jar

Sorry, I though everyone would catch on to that one. :slight_smile:

Pretty solid. Sound lags a bit, but the timing and everything seems OK.

Michael Bishop