expensive input polls

Started by Qudus, January 19, 2008, 02:00:22

Previous topic - Next topic

Qudus

In my benchmark (the Q3 flight one) polling keyboard and mouse (each frame) costs me 3% of the resulting 213 FPS. This is quite a lot. And using YourKit to profile the benachmark I found out, that the Keyboard and Mouse are polled again in the Display.update() method.

So it seems, that calling Keyboard.poll() and Mouse.poll() is unnecessary, if Display.update() is used. Is this correct? In my input test (in the other thread here in this forum) I discussed a problem with the input on Windows, which was caused by the poll() method not called by my input system even if Display.update() was called.

So is it correct, that Keyboard.poll() and Mouse.poll() have to be called before querying the input state changes? Or is this unnecessary?

Is there a way to improve the input polling performance?

Marvin

Qudus

From reading Display's source I found out, that I can simply call
if ( Display.isVisible() || Display.isDirty() )
{
    Display.swapBuffers();
}

instead of
Display.update();

This will result in the input devices not being polled, which I can do, when I need it. My test has become faster now :). And the pollMessages() method is not needed to be called, since it does nothing else than
display_impl.update();

which is already done by the isVisible() and isDirty() calls. I suggest to change that in the source, since it just costs performance.

And is it really necessary to call display_impl from within each method. I would like to have methods like isVisible() and isDirty(), that don't call display_impl.update() (maybe an additional boolean parameter), since it costs me 1% for each of these calls. And as far as I understand it, this display_impl.update() method should only be necessary to be called once per frame. Is this correct?

My initial question stays though. Is it possible to do input polling in a cheaper way?

Marvin

Qudus

After further profiling I found out, that polling Keyboard and mouse both internally calls LinuxDisplay.update() multiple times. This should be changed. It is the most important reason for expensive input polls.

I would offer to do this, but since I am not to familiar with LWGJL internals, I would risk to mess things up. Could please somebody of the LWJGL gurus do this? Would be very cool.

Thanks.
Marvin

Matzon

elias comitted some changes - can you compile and run from SVN ?

elias

Thank you for investigating this issue. I've removed the update()s from the poll() and read() methods, but I'm not sure how to remove the one in Display.update(), without breaking existing LWJGL programs. For example, a program might never call isDirty() or isActive(), making the processMessages() call in Display important. Ideally, a program should:

Display.processMessages();
if (Display.isVisible() || Display.isDirty()){
    Display.swapBuffers();
} else {
    try { Thread.sleep(A_WHILE); } catch (InterruptedException e) {}
}


where neither isVisible() nor isDirty() should call processMessages().

- elias

elias

I also changed Display.update() to only call display_impl.update() once, by replacing isVisible() and isDirty() with display_impl.isVisible() and display_impl.isDirty().

- elias

Qudus

Quote from: Matzon on January 19, 2008, 09:14:02
elias comitted some changes - can you compile and run from SVN ?

Unfortunately not. I pulled the SVN trunk three days ago and tried to make it compilable in eclipse. But it seems, that there are classes (in the generated folder), that need to be generated (by an ant task, I assume). and since I don't have a working ant environment, I cannot compile the source. Would be great, if I could download a nightly build somewhere.

Quote from: elias on January 19, 2008, 09:15:33
Thank you for investigating this issue.

You're welcome. It is the least I can do to give something back to you making this great library :).

Quote from: elias on January 19, 2008, 09:15:33
I've removed the update()s from the poll() and read() methods, but I'm not sure how to remove the one in Display.update(), without breaking existing LWJGL programs.

This could be easily done by overloading the Display.update() method with one, that has an additional boolean parameter, that tells, if these sub-updates and polls are to be done.

Quote from: elias on January 19, 2008, 09:15:33
For example, a program might never call isDirty() or isActive(), making the processMessages() call in Display important. Ideally, a program should:

Display.processMessages();
if (Display.isVisible() || Display.isDirty()){
    Display.swapBuffers();
} else {
    try { Thread.sleep(A_WHILE); } catch (InterruptedException e) {}
}


where neither isVisible() nor isDirty() should call processMessages().

Well, simply overload the isVisible() and isDirty() methods, too with this additional boolean. And then simply forward the boolean from Display.update(boolean).

Thanks again.

Marvin

Qudus

I tried the new 1.1.4 release. And this is my result:
Before I can actually poll the input I have to call Display.processMessages(), if I didn't call any other method, that calls display_impl.update() before. This is principally ok. But it leads me to the conclusion, that display_impl.update() works in a too general way. Is there a way to only process the input related messages, since polling input is still very expensive, if it needs a call to processMessages()?

Marvin

elias

Surely you already call processMessages once per loop? There's no way to filter out input related messages from display_impl.update().

- elias

Qudus

Quote from: elias on January 21, 2008, 20:17:33
Surely you already call processMessages once per loop? There's no way to filter out input related messages from display_impl.update().

Well, I call it before polling input only. It doesn't seem to be necessary to be called for anything else. Rendering is done without any problems without the call to display_impl.update(). I don't need the isDirty() check and if isVisible() steals me 4% of rendering performance in my testcase (because of the implicit call to display_impl.update(), I don't need/want it neither. This is exactly, why I ask so vehemently ;).

Marvin

elias

You won't get good behaviour if you don't process the messages from the windowing system, so a call to processMessages() is required, at least once in a while.

- elias

Qudus

Quote from: elias on January 21, 2008, 21:04:51
You won't get good behaviour if you don't process the messages from the windowing system, so a call to processMessages() is required, at least once in a while.

And polling the window-messages is the expensive part? If this is true, there's definitely a need for the users to poll different things separately to manage, when to poll what.

What would be the expected problems, if window-messages are never polled?
Would it be sufficient to poll the window-messages each (e.g.) 100-th frame?

Marvin

elias

Window messages includes mouse and keyboard messages, so I can't see how you would avoid it. You can filter events when polling to exclude anything else than input events, but I don't think that's the expensive part.

- elias

Qudus

I tried to get a closer look at the polling methods. But I can't find the implementation of the XPending method. Is it true, that to input methods are all polled? If it is true, can't this be done through a callback? Shouldn't this be much faster?

After I further tuned Xith3D the time part, that is taken for the display_impl.update() call is getting higher. Now it is 6% (of 470 FPS). So this is getting more and more annoying the more I tune my own code.

Marvin

Matzon

it would be relevant to locate the part of update that is taking a long time. Fwiw, you should poll every time you render a frame. Furthermore I am not sure that you can - or even should - do it using somekind of callback mechanism.