Speed: Windows >>> OS X? Am I missing something?

Started by directedchaos, August 31, 2007, 02:35:27

Previous topic - Next topic

directedchaos

I recently restarted development on a lwjgl game and noticed it seemed to be very slow on my macbook pro: around 15-20fps (with dips in the low teens).  I restarted in Windows XP (same machine, dual boot), and it's a steady ~60fps (seems capped even).  Exact same builds of my game.

This doesn't seem right.  Anyone ever had a similar experience?

Some more quirks: XP detects 60hz refresh rates, while OS X does the 0hz filler (all available modes are 0hz).  Is this ok?

I realize this is very little to go on, but I didn't want to drown you with details about the game -- particularly since it looks like I'll have to comb back over the engine and find the bottlenecks for comparison (of course, if that does sound exciting, I could update this with more speed tests with various rendering/engine sections cut out :P).  I just wanted to test the waters and see if anyone had come across this and/or had any suggestions.  15fps vs 60fps... :S

Thank you for your time!

directedchaos

I gather this isn't a common phenomenon.  A few profiling experiments later and I'm still at a loss; it just seems to be slower, at everything.  Over half of the time is spent purely in openGL calls (nearly 70% -- glBegin is about 30%!); everything I turn off gives steady speed boosts.  I'm not an expert at profiling (just used a Netbeans profiler, mainly looking at functions' self times, which excludes other method calls), but I'm pretty sure there is no game logic bottleneck (the game engine -- physics, ai, etc. -- takes about 4%).

The final scene averages maybe 100 small (~64x64) textured quads.  Surely I'm not hitting my GeForce 8600M GT's fill rate. 

Do you know a way I can verify that it's using the gpu and not software rendering?

15-20fps seems awfully low for such a simple 2d engine :-/ (especially, again, considering the 60fps on XP).

Thank you for reading this!


elias4444

I'm personally at a loss for what to tell you. I develop all my games on a Mac, and they seem to run the same whether I'm on a Mac or in Windows. Are you sure you're using the same displaymode for both systems in your initialization?

Also, how are you handling the screen vsync?
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

directedchaos

Quote from: elias4444 on September 04, 2007, 15:38:41
I'm personally at a loss for what to tell you. I develop all my games on a Mac, and they seem to run the same whether I'm on a Mac or in Windows. Are you sure you're using the same displaymode for both systems in your initialization?

Also, how are you handling the screen vsync?


Hey, thank you for responding!  The only display difference between the two systems is that XP finds 60hz refresh rates, while OS X does the 0 hz thing (it's a laptop, I gather that's the norm as a filler for whatever its actual rate is, maybe only the OS knows).  Normally vsync  is enabled (standard for games, right?) but I tried disabling it and nothing seemed to change.

Should gl calls be taking up that much time?

Also, everything is done in one thread.  I experimented with multiple threads but the overhead of splitting up the work then recombining it in 1/60th of a second seemed too much (particularly with the engine hovering in such a small % of the worktime).  I may also have been doing inefficient object creation, so I could revisit it as another means to speed up the game.

Finally, if it isn't obvious, I'm not a professional -- this is a hobby project (albeit long in the making).

I was planning to wait until I got some final features hammered down, but perhaps I should compile a speed test demo.  I'll try to spruce one up for tonight, and would appreciate specs and fps.  Should I post it here or a new thread?

Let me know if you have any other ideas!

elias4444

I'd say go ahead and post it here for some bug catching, and then, once it's spruced up, post it in a new thread for everyone to try.

Just my opinion though.  ;)
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

directedchaos

Alright, here's a rough-and-dirty demo:
http://www.directedchaos.net/files/games/ff/FF_latest_build.zip (2.6mb)

It's a simple overhead 2d engine, aimed mainly for medieval fantasy.  I called it Futile Fantasy, though that name is probably taken by some other cooler game, and you can read more details about it here:
http://www.directedchaos.net/pages/ff/index.php

You should be able to double-click Futile_Fantasy.jar to run it, wherever you dl it to.  You can change some display settings in "settings.txt" and game settings (such as keybindings and scenario directory) in "prefs.txt".  You shouldn't have to change anything.  If you're just doing this to be nice to me and give me an FPS number, here's the basics:
a,w,s,d: left, forward, backward, right
p: "quick" save
o: "quick" load (latest save)
v: open/close door ("activate terrain")
c: loot ("activate object")
return: toggle fps display

If you decide you actual want to play it, but find it too slow, you can try turning off the map (bottom right of the screen) by clicking the x button in its bottom-left corner.  Also, you can zoom in/out using +/- keys or middle mouse scroll (fewer tiles/creatures=faster).  Staring at the 3 tiles around me I can get like 50fps...
Hopefully, though, there's some fun in the little scenario.  Despite the very very very crude graphics.

There are bound to be bugs, and while I welcome any reports, don't feel obligated to hunt them down!  This is above all a simple speed test; I need the engine to be playable.

Oh, one serious known bug: you cannot save if you're using 1.6. 1.5, which I test on as the OS X standard, runs fine.  I had to fiddle with it on Windows to revert back to 1.5 so I could do saving/loading.  The problem deals with object serialization, and I'm a total noob at that.  But 1.5 should work fine.  Let me know if it doesn't!

Some, probably not comprehensive, acknowledgements:
-GLApp.java base, from napier@potatoland.org
-TextureLoader by Kevin Glass and Brian Matzon, from spaceinvaders

Thank you for reading this!

princec

Got this:

(WinXP)
org.lwjgl.openal.OpenALException: Invalid Value
        at org.lwjgl.openal.Util.checkALCError(Util.java:55)
        at org.lwjgl.openal.ALC10.alcGetInteger(ALC10.java:184)
        at org.lwjgl.openal.ALC11.initialize(ALC11.java:172)
        at org.lwjgl.openal.AL.init(AL.java:180)
        at org.lwjgl.openal.AL.create(AL.java:140)
        at org.lwjgl.openal.AL.create(AL.java:104)
        at org.lwjgl.openal.AL.create(AL.java:191)
        at futilefantasy.MainGameWindow.init(MainGameWindow.java:103)
        at futilefantasy.MainGameWindow.start(MainGameWindow.java:120)
        at futilefantasy.Main.main(Main.java:74)


Cas :)

directedchaos

Hey, thank you for the feedback!  Sorry it didn't work -- it didn't even start, how embarrassing!  I'll put some musings here, don't feel obligated to help me track down the bug.

It looks like a toughy.  It's crashing on AL.create(), but works on my machine (OS X and Windows, macbook pro).  I suppose I should post in the openAL forum?  I have no idea how to interpret that :(

Things that happened before it crashed (the log should verify this):
-created display
-created input
-created opengl

The exact line it failed on:
AL.create();

My best guess is that it's not finding the natives properly, even though they are in the same folder as the jar.  If you or anyone else gets this problem again, try running it command-line adding:
-Djava.library.path="C:\absolute\path\to\FF_game_dir"

Again, no worries if you don't, and thank you for your time!

princec

Everything worked up to that point - got a display and everything - you just passed an invalid value into AL.create() somehow. Are you using the default initialization, or doing some other monkeying?

Cas :)

directedchaos

Hah, I don't know enough to monkey; it's the default (empty) create method.  Here's the code:

//other initialization: display, input, opengl
try {
    AL.create(); //dies here!
} catch (LWJGLException ex) {
    ex.printStackTrace();
}
AL10.alGetError();


I don't get it.  Works on mine :( Thank you for trying!  I'm open to any ideas -- in what cases will AL.create() fail?  This is the first line (in execution) that even mentions AL.

elias

My guess is that it is using the system supplied openal32.dll. Try bundling the openal32.dll from lwjgl instead, and make sure lwjgl can find it.

- elias

directedchaos

I really don't know what to say about the sound crash.  I do include all the lwjgl natives in the same directory as the executable JAR.  I've tried experimenting with putting them in a separate folder and editing the manifest, but it wouldn't find them.  Just in case, I still include them in the manifest file classpath, alongside the lwjgl JARs.

Manifest file:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 1.5.0_07-87 ("Apple Computer, Inc.")
Main-Class: futilefantasy.Main
Class-Path: ./lwjgl/lwjgl.jar ./lwjgl/jinput.jar ./lwjgl/lwjgl_test.ja
 r ./lwjgl/lwjgl_util_applet.jar ./lwjgl/lwjgl_util.jar ./jinput-dx8.d
 ll ./jinput-raw.dll ./libjinput-linux.so ./libjinput-osx.jnilib ./lib
 lwjgl.jnilib ./liblwjgl.so ./liblwjgl64.so ./libopenal.so ./lwjgl.dll
  ./openal.dylib ./OpenAL32.dll
X-COMMENT: Main-Class will be added automatically by build


I do have some good news though!  I've been digging deep into the cause of the slowdown on the OS X side, and rewrote the drawing routines to include a simple scenegraph which shoots up the fps to near that of XP.  Basically, I was very naive about the capabilities of openGL and was switching textures and starting quads willy-nilly.  I gather now that you're supposed to group them to minimize texture switches and glBegins, among other things (strangely enough, quad strips didn't seem all that effective, probably because of the higher glBegins required to create distinct strip ranges).  Anywho, it's much more playable.  Here's a recent snap:



Don't mind the 30fps, it was generally 55-60 (probably messing around with other stuff + screenshot).  However, there is some weird hiccup that drops it ~5fps every couple seconds, sometimes, then bounces back up.  Very elusive.  Replaced FF_latest_build.zip (~2.6mb)

One caveat: it does slow down significantly when moving with the map on auto-follow.  The map is automatically rendered to a texture if left alone for a second.

elias

You can check which openal library is loaded by enabling lwjgl debugging (java -Dorg.lwjgl.util.Debug=true ...) and looking at the lwjgl debug output.

- elias

directedchaos

Thank you!  It looks like the exact opposite of what I thought.  XP is finding OpenAL32.dll in the game directory, while OS X is not finding openal.dylib in the game directory.  However, XP does search the system32 directory first.  Does anybody know a way to force it to search the current directory first, preferably via something in the manifest file?  Writing custom scripts for each OS seems a little counterproductive (and I don't know how to do that).

The biggest problem atm is not finding openal.dylib.  :-/  It just mysteriously says "Found openAL bundle."

Here's some output, if you're feeling overly generous:
([...] = snipped absolute path to game directory)
OS X: java -Dorg.lwjgl.util.Debug=true -jar Futile_Fantasy.jar
getPathFromClassLoader: searching for: openal
Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.URLClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.security.SecureClassLoader.findLibrary(java.lang.String)
getPathFromClassLoader: searching for: lwjgl
Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.Launcher$AppClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.URLClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.security.SecureClassLoader.findLibrary(java.lang.String)
Found 6 OpenAL paths
Testing './openal.dylib'
Failed to load ./openal.dylib: Could not load OpenAL library
Testing '/Library/Java/Extensions/openal.dylib'
Failed to load /Library/Java/Extensions/openal.dylib: Could not load OpenAL library
Testing '/System/Library/Java/Extensions/openal.dylib'
Failed to load /System/Library/Java/Extensions/openal.dylib: Could not load OpenAL library
Testing '/usr/lib/java/openal.dylib'
Failed to load /usr/lib/java/openal.dylib: Could not load OpenAL library
Testing '/[...]/FF_latest_build/openal.dylib'
Failed to load /[...]/FF_latest_build/openal.dylib: Could not load OpenAL library
Testing 'openal.dylib'
Failed to load openal.dylib: Could not load OpenAL library
Found OpenAL Bundle

At this point it proceeds to create sources and make all sorts of silly sounds (that I recorded).

OS X: java -Djava.library.path=/[...]/FF_latest_build -Dorg.lwjgl.util.Debug=true -jar Futile_Fantasy.jar
Same as above, but only found 3 paths:
Found 3 OpenAL paths
Testing '/[...]/FF_latest_build/openal.dylib'
Failed to load /[...]/FF_latest_build/openal.dylib: Could not load OpenAL library
Testing '/[...]/FF_latest_build/openal.dylib'
Failed to load /[...]/FF_latest_build/openal.dylib: Could not load OpenAL library
Testing 'openal.dylib'
Failed to load openal.dylib: Could not load OpenAL library
Found OpenAL Bundle


XP: java -Dorg.lwjgl.util.Debug=true -jar Futile_Fantasy.jar
Similar, but sucessful:
getPathFromClassLoader: searching for: OpenAL32
Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.L
auncher$AppClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.U
RLClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.secur
ity.SecureClassLoader.findLibrary(java.lang.String)
getPathFromClassLoader: searching for: lwjgl
Failed to locate findLibrary method: java.lang.NoSuchMethodException: sun.misc.L
auncher$AppClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.net.U
RLClassLoader.findLibrary(java.lang.String)
Failed to locate findLibrary method: java.lang.NoSuchMethodException: java.secur
ity.SecureClassLoader.findLibrary(java.lang.String)
Found 10 OpenAL paths
Testing 'C:\WINDOWS\system32\OpenAL32.dll'
Failed to load C:\WINDOWS\system32\OpenAL32.dll: Could not load OpenAL library
Testing '.\OpenAL32.dll'
Found OpenAL at '.\OpenAL32.dll'


XP: java -Dorg.lwjgl.util.Debug=true -Djava.library.path="C:\[...]\FF_latest_build" -jar Futile_Fantasy.jar
(again, same as above but only 3 openAL paths, but this time it finds it first go)
Found 3 OpenAL paths
Testing 'C:\[...]\FF_latest_b
uild\OpenAL32.dll'
Found OpenAL at 'C:\[...]\OpenAL32.dll'


Again, thank you for your time!

elias

LWJGL first looks at what the current ClassLoader.findLibrary returns, which is important for web start where the location of native libraries are not given by java.library.path. Then it looks at java.library.path and finally it lets the OS do the search.

The "Found OpenAL bundle" is printed when lwjgl falls back to the built in mac os x library (which is in a so-called bundle).

If you're hearing weird noises instead of proper sound and you're using a PPC mac, make sure you give OpenAL sound samples with the correct endianness (PPC is big-endian, intel is little-endian), which usually means you create a ShortBuffer ordered with ByteOrder.nativeOrder() and copy from samples from another ShortBuffer ordered in the file order (for wav, this means little-endian). Finally, the first buffer is used to upload sound with alBufferData.

- elias