[SOLVED] Ghost thread eating performance! LWJGL...

So I got a lot of my programming sorted out recently and managed to get a playable part of my game working. However, I saw horrid performance. Playing around with it for a while, I realized that it “goes away” after a while, doubling my FPS like a flip of a switch. The time it takes for it to start running decently is completely random. Sometimes it’s instant, sometime’s it’s more than a minute, which is obviously unacceptable.
First I obviously checked if anything else was running in the background. Nothing. Then I saw that my game’s java.exe dances at around 40-45% processor usage during this time, dropping to 25% (100% on one of four cores) when the game starts running as it should. The game doesn’t even create a single thread manually, so it should be impossible for it to use 100% on one core (25% in the task manager). I’m basically having a ghost thread draining CPU power in some weird way. I’ve tried to monitor threads with the profiler in Netbeans, but I can’t see any thread stopping or pausing when the lag disappears.

PS: Lol, Minecraft seems to get this too.

You’re not by any chance using the sleeping thread trick to fix timing issues on windows? (I do know that minecraft uses this).

Like I said, I’m not doing anything with threads. I’m gonna try to use that trick now.
EDIT: Nope, nothing. Sigh… Just added a very CPU bound feature, and now it doesn’t speed up even after waiting minutes. What the heck is doing that?! I’ve even tried both JDK 6 and 7!

[quote]Like I said, I’m not doing anything with threads.
[/quote]
Your game isn’t doing anything on threads? Or do I misunderstand?

Java runs multiple threads in and of itself, and if you aren’t organising your program’s components into threads, Java will try to run everything on a single thread. That being said, it will probably be really slow, and it will probably eat up CPU.

I’m not creating even a single Thread object, so the fact that another thread slows down my game seems to point to a problem with LWJGL. No problem occurs if I run the exact same code, but without rendering. The scary part is that I can’t identify WHICH thread is eating performance.

What happens when you put a sleep(100) in your mainloop?

This might seem like an odd question, but it might be a multi-threaded GPU driver, that will also ‘calm down’ when you make your game idling.

Can you post a reproducer so that we can try it on our systems?

I’ve been using lwjgl 2.7.1 on Mac Snow Leopard with Java 1.6.0_26 for the last couple of months and haven’t had any trouble with lwjgl’s performance or rogue processes.

Sorry slightly of topic but is this the sleep trick your talking about?


Thread sleeper = new Thread(new Runnable()
{
   public void run()
   {
      while(true)
         try
         {
            Thread.sleep(Long.MAX_VALUE);
         }catch(InterruptedException e)
         {
         }
   }
});
sleeper.setDaemon(true);
sleeper.start();

FOUND IT! Damn you, Threaded optimization!
The problem relates to the setting Threaded optimization in the Nvidia control panel! The ghost thread was a video driver thread! I’ve actually been experimenting with that setting. The default is Auto, which apparently tries to use multithreading when the game is started and then falls back to single threading when it realizes it gets better performance for less CPU power from that after often less than a second. HOWEVER, if what you’re doing is very CPU heavy (i.e. the graphics card is idling a lot) which I was doing it will apparently not fall back as it should. Setting the setting to Off solves this.
Thanks to everyone who posted, especially Riven! xD And yes, that is the exact same sleep fix that I used (except I didn’t use an infinite loop, fixed xD).

Yup, that’s the one (or a variation of it).

Cool… so is it only needed on Windows? Does it really help if you have it running on Mac or Linux?

It won’t help, its a Windows specific fix in the JVM. As long as a thread is asleep the JVM keeps the resolution at 1ms to make waking up threads/locks/timers more precise. As soon as there is no sleeping thread the resolution is reset to the default 10 or 15ms (system dependent, happy happy joy joy).

Because the precision is already high enough (1-2ms) on Linux or Mac platforms out of the box, the JVM for those platforms does not have the workaround and so the sleeping thread trick adds nothing.

So basically:


if(System.getProperty("os.name").startsWith("Win")) {
    new Thread() {
        {
            setDaemon(true);
            start();
        }
        
        public void run() {
            while(true)
                try{
                    Thread.sleep(Long.MAX_VALUE);
                }
                catch(Exception exc) {}
        }
    }
}

Hm we should probably just build this in to LWJGL.

Cas :slight_smile:

As apposed to the JVM itself, yes. Sun already attempted that once with a command line switch, but they managed to fail in a very epic way:

http://bugs.sun.com/view_bug.do?bug_id=6435126

Note that the sleeping thread hack fix is actually mentioned as a workaround to this bug!

Why is it needed? what does it fix?

Wow, that is epic fail indeed. Whats even worse is that they want to keep the broken switch in there.

In Windows, the default resolution of the timer is about 10 ms. This trick forces the JVM to use the High Resolution timer for more accurate sleeping.

Wanted. Sun is gone, Oracle is now in charge. Seeing what the last dozen updates to Java 6 have brought, it is clear that Oracle is more inclined to apply fixes that break backwards compatibility. What I don’t like is that they often do so silently :confused: