LWJGL
May 21, 2013, 06:07:44 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: LWJGL is now using GitHub
 
   Home   Help Search Login Register  



Pages: [1]
  Print  
Author Topic: Little "lags" ?  (Read 3395 times)
PinkieSwirl
Newbie
*
Posts: 12



« on: February 19, 2012, 04:27:00 »

I get some little "lags", when i play a lwjgl application in 2D, for example the space invaders example game, or my own. Tested this on different computers (windows) with different java versions with lwjgl 2.8.3.
When i play at ~60 fps, the lag occurs every second (the sprites jump a little bit, if they move).
Logged
kappa
Administrator
Nerdus Imperius
*****
Posts: 1112



« Reply #1 on: February 19, 2012, 05:02:57 »

how is the fps capped? using Display.sync(60), vSync() or some other method?
Logged
Jonas
Newbie
*
Posts: 6


« Reply #2 on: February 19, 2012, 05:31:28 »

It might be garbage collection kicking in?  That can have a minor, yet noticeable effect for 1-2 frames, and tends to happen at fairly regular intervals.  You might try giving -XX:+UseConcMarkSweepGC as a VM argument to switch to a different garbage collection method, that helped me a bit when I had a similar situation.
Logged
PinkieSwirl
Newbie
*
Posts: 12



« Reply #3 on: February 19, 2012, 05:48:08 »

In my project i use Display.sync(60) with an option for vSync.
Something like this:

Code:
initDisplay(){
 ...
 Display.setVSyncEnabled(vSync);
}
loop() {
 ...
 Display.update();
 Display.sync(60);
}

On my pc with a intel hd "videocard", vsync has no impact?
On my other pc with a real card vsync limits the framerate.

But the lag occurs even when i do something like this:
Code:
long time = getTime();
 ...
 time = 16 - (getTime() - time);
 if (time >= 1)
  Thread.sleep(time);

Thats why i thought i do something wrong in my render function, but in the space invaders example the lag occurs too. So...?

EDIT:
It might be garbage collection kicking in?  That can have a minor, yet noticeable effect for 1-2 frames, and tends to happen at fairly regular intervals.  You might try giving -XX:+UseConcMarkSweepGC as a VM argument to switch to a different garbage collection method, that helped me a bit when I had a similar situation.

I tried it but it has no effect (I just put "-XX:+UseConcMarkSweepGC" as an argument thats right?). And the lag isn't that minor~
Logged
princec
Nerdus Imperius
*****
Posts: 1868



WWW
« Reply #4 on: February 19, 2012, 15:10:12 »

Thread.sleep() is not especially accurate.

Cas Smiley
Logged

PinkieSwirl
Newbie
*
Posts: 12



« Reply #5 on: February 20, 2012, 01:50:54 »

I know but thats not the point Cheesy.

The problem is, it lags, but the framerate is constant at 63 fps (or 60 with vsync).

Before using lwjgl i used java2d for basic game developing / learning. And this lag occurs never, even with Thread.sleep().
Logged
princec
Nerdus Imperius
*****
Posts: 1868



WWW
« Reply #6 on: February 20, 2012, 02:52:56 »

63fps is not exactly the right speed is it Smiley

Cas Smiley
Logged

matheus23
Regular nerd
**
Posts: 62


« Reply #7 on: March 19, 2012, 14:13:33 »

@Cas:
This is, because he is using
Code:
time = 16 - (getTime() - time);
, and this is kind of inaccurate, because he should acctually sleep 16.6666* ms.

Maybe the problem is, that you use both Display.sync() and your own sleep too. (Are you doing it like that, or did I missunderstood that?)
Logged

My github account and currently active project: https://github.com/matheus23/UniverseEngine
CodeBunny
Nerdus Imperius
*****
Posts: 561



WWW
« Reply #8 on: March 19, 2012, 20:41:03 »

I've had my games run at 63 fps before, when I am only using Display.sync(60). This definitely happens on more than one machine.

It's true, I do not have v-sync on, but still; my fps should be set to 60 but it isn't.

And yes, I see the "little lags" PinkySwirl mentioned from time to time. It's one of those issues I've always meant to look into but never really focused on.
Logged
matheus23
Regular nerd
**
Posts: 62


« Reply #9 on: March 20, 2012, 10:44:16 »

@CodeBunny

This is because, you usually compute the number of time your game has to wait in one frame. Usually you say:
Code:
int frameTime = 1000 / 60;
now acctually, if you divide 1000 by 60, you get 16.66666*, but as it is an int, (or long) frameTime will be set to 16. That means, your game will slightly sleep less, than it acctually should. If you run the game, you will get 63 fps, because he will only calculate the fps, if 1000ms are gone since the last second. That means, if you would take 16 ms per frame for 60 frames, you will have passed 16 * 60 = 960 [ms]. But acctually the fps counter waits for 1000ms, so you need 3 more frames to get above 1000ms: 16 * 63 = 1008.

You can easily solve the problem with "High Resolution" Timers. The standard Java library allows that (via milliseconds AND nanoseconds (See Thread.sleep and System.nanoTime()), just take a look at this:
Code:
private class DelayHandler implements UniPrintable {

/* Delay-Handling: */
private HighResTime sleep;
private HighResTime delta;
private HighResTime timeOld;
private HighResTime time;
private HighResTime fpsTime;
private HighResTime realSleepBegin;
private HighResTime realSleepEnd;
private HighResTime realSleep;

/* FPS-Handling: */
public float fps;
private long frames;
private HighResTime fpsTimeOld;
private long up;

public DelayHandler() {
sleep = new HighResTime(0, 0);
delta = new HighResTime(0, 0);
timeOld = new HighResTime(0, 0);
time = new HighResTime(0, 0);
fpsTime = new HighResTime(0, 0);
realSleepBegin = new HighResTime(0, 0);
realSleepEnd = new HighResTime(0, 0);
realSleep = new HighResTime(0, 0);
fps = 0f;
frames = 0;
fpsTimeOld = new HighResTime(0, 0);
up = 60;
setFpsTime(60);
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}

private HighResTime getDelta() {
frames++;
time.set();
delta.setSubtract(time, timeOld);

if (frames >= up) {
fps = ((up * 1000f) / (time.time - fpsTimeOld.time));
frames = 0;
UniPrint.printf("%s >> fps: %G\n", getClassName(), fps);
fpsTimeOld.set(time.time, time.timeNano);
}

return delta;
}

/**
* Call this after every frame.
*
* @param fps
*            - The wanted FPS to sync to.
* @return whether you should exit the loop or not.
*/
public boolean update(boolean dodelay) {
sleep.setSubtract(fpsTime, getDelta());
sleep.normalizeNano();
if (dodelay) {
try {
realSleepBegin.set();
while (sleep.time > 0) {
Thread.sleep(sleep.time, (int) sleep.timeNano);
realSleepEnd.set();
realSleep.setSubtract(realSleepEnd, realSleepBegin);
sleep.setSubtract(sleep, realSleep);
}
timeOld.set();
return false;
} catch (InterruptedException e) {
UniPrint.printerrf(this, "Error while sleeping!\n");
e.printStackTrace();
return true;
}
}
return false;
}

public void setFpsTime(long fps) {
fpsTime.set(1000L/fps, (1000000000L/fps)%1000000L);
}

/**
* Set how much frames to wait, until the next
* frame rate is printed. Also affects fps
* calculation, because fps are calculated,
* when they are printed.
* @param frames - the frames to wait.
*/
public void setFpsCalcDelay(long frames) {
up = frames;
}

public String getClassName() {
return getClass().getSimpleName();
}

private class HighResTime {

public long timeNano;
public long time;

public HighResTime(long timeNano, long time) {
this.timeNano = timeNano;
this.time = time;
}

public void set() {
timeNano = System.nanoTime();
time = System.currentTimeMillis();
}

public void set(long t, long tn) {
time = t;
timeNano = tn;
}

public void setSubtract(HighResTime t1, HighResTime t2) {
timeNano = t1.timeNano - t2.timeNano;
time = t1.time -t2.time;
}

public void normalizeNano() {
timeNano = timeNano % 1000000L;
timeNano = timeNano < 0 ? timeNano+1000000L : timeNano;
}

}
}
(This is code from my UniverseEngine Smiley )
The Code is not very good written and documented (cause its private), but it should give you an idea Smiley

[EDIT: Little corrections...]
Logged

My github account and currently active project: https://github.com/matheus23/UniverseEngine
CodeBunny
Nerdus Imperius
*****
Posts: 561



WWW
« Reply #10 on: March 21, 2012, 08:10:03 »

I understand how to do it on my own; I'm talking about using the standard LWJGL call Display.sync (which is what should be used, because it's supposed to package all of the logic you are talking about. The problem is more that the standard API call is not correct, not that I'm unable to create my own method of keeping framerate.

It's getting fixed, though. There's a topic here: http://lwjgl.org/forum/index.php/topic,4452.0.html.
Logged
CodeBunny
Nerdus Imperius
*****
Posts: 561



WWW
« Reply #11 on: March 21, 2012, 08:14:01 »

Also are you sure your code is optimal? The main problem is that using Thread.sleep and similar functions results in poor behavior, because those methods do not always result in perfect timing.
Logged
matheus23
Regular nerd
**
Posts: 62


« Reply #12 on: March 21, 2012, 10:42:25 »

@CodeBunny:
1st: Oh, sorry, misunderstood that Smiley
2nd: Hmm.... The only other ways of implementing sleep is the "Native" way: sleep() (for windows) and usleep() (for everything else (?)). But I have never used JNI, and I'm not planning to do it... The only other way of Thread.sleep()-kind methods is the LockSupport (or something like that :/, Googleing it showed, that thats not the name ...), which I tried out too, but was muuuuuch worse. And as it is a personal interest too: Is there a good alternative too Thread.sleep() ? Many people ask for something like that.
Logged

My github account and currently active project: https://github.com/matheus23/UniverseEngine
CodeBunny
Nerdus Imperius
*****
Posts: 561



WWW
« Reply #13 on: March 21, 2012, 21:25:15 »

That's actually what this thread (http://lwjgl.org/forum/index.php/topic,4452.0.html) is entirely about - apparently, it's difficult to get a truly optimal game loop framerate.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines
SMFAds for Free Forums
Valid XHTML 1.0! Valid CSS!