Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  libgdx: Terrible performance with very few draw calls  (Read 3429 times)
0 Members and 1 Guest are viewing this topic.
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Posted 2013-08-29 00:37:02 »

I got a bit of a shock today when I tried the game I've been working on with a proper device and found that my tiny game is running at about 20fps. Sad

In-game, at the moment I've got 16 tiles, one sprite, 6 patches and 6 bitmap font draw calls. On an S4 I'd hope that'd be capable of hitting 60fps without breaking a sweat.

Simplifying it, my hacked main menu now just has 20 tiny buttons on it, which is each a single call to BitmapFont.draw and NinePatch.draw. This gets ~15fps.

I have a single libgdx Stage.draw() set to the full screen res, and a second SpriteBatch that's just used to draw the fps text. The app is set to use GL2.0, but it doesn't make a different to the fps either way. Just drawing the fps display gets me a solid 60fps.

Textures are only being loaded at startup. Fillrate doesn't seem to be an issue since it occurs no matter how small I make the buttons.

DDMS's frame time measurement says it's taking 68ms to 'Process', whatever that covers, with 'Draw' at 9ms and 'Execute' at 0.7ms.

I'm fairly sure I must be doing something stupid here since I'm new to libgdx. Anyone have any pointers? Thanks.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #1 - Posted 2013-08-29 03:13:36 »

Could you be accidentally calling some "new _____"  inside your draw/render loop?

I once accidentally called `new ShapeRenderer()` inside my render loop and it killed my frame rate to like 5% of what it should have been.

"Experience is what you get when you did not get what you wanted"
Offline davedes
« Reply #2 - Posted 2013-08-29 03:39:11 »

Here's a bunch of Android considerations:

  • How many draw calls are you actually getting? It should be really low if you only have a few textures. Test like so:
1  
2  
3  
4  
5  
6  
7  
8  
SpriteBatch.totalRenderCalls = 0;

// ... render entire scene here ... //

int calls = SpriteBatch.totalRenderCalls;

//Log or render to screen
System.out.print(calls);
  • Your shader code needs to be highly optimized (if you are doing anything there). Avoid stuff like dependent texture reads and branches
  • Make sure you're packing textures as much as you can. You can use PixmapPacker to pack at runtime. Ideally, if you can fit all textures into a single atlas it should lead to significant boost in performance.
  • Try not to use two sprite batches. This leads to two shaders (and possibly two VBOs), and thus state switches which can be costly on mobile. If you must use two batches, you can pass shared shaders and Mesh buffers to the constructor.
  • Avoid allocations like namrog84 said. Especially stuff like Strings concatenation. LibGDX includes a StringBuffer implementation which is really low on allocations, and great for rendering frequently changing text and numbers.
  • If you are using Groups for your scene2D graph, it might lead to batch flushes
  • If you're finding text rendering to be the slowdown, other than tightly packed atlases you can also look into using BitmapFontCache directly. This caches the vertex data for each glyph which leads to a slight boost.
  • Similarly, you can use SpriteCache instead of SpriteBatch to see if caching vertex data improves performance. This is probably negligible at this point in your game, though!
  • Use nearest filtering where possible and POT textures

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #3 - Posted 2013-08-29 09:36:33 »

From some more poking I'm getting 40 batches per frame, which doesn't sound like a lot but could be part of the problem.

I'm doing something like this:
1  
2  
3  
4  
5  
6  
7  
8  
class TextButton extends Actor
{
  public void draw(SpriteBatch batch)
  {
     patch.draw(batch);
     text.draw(batch);
  }
}

This seems to be causing a draw batch for every button since the nine patch and text use different textures. Is there a way to layer these at runtime via sprite batch (so all text is drawn over the top), or do I need to start merging the textures into an atlas somehow?

Also I can't see how I'd avoid having two batches if I want to draw the fps text separately. Stage doesn't expose the sprite batch. I guess I could add an Actor for the fps but that seems like a sledgehammer to crack a nut.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #4 - Posted 2013-08-29 09:53:50 »

Its very easy to use the Atlas in libgdx
Can be pretty much done in 2 lines,  a texture atlas, then findregion

1  
2  
3  
4  
5  
6  
//Art.loaded up earlier on
TextureAtlas myTextures = new TextureAtlas("data/art.txt");

TextureRegion playerFrontTR = myTextures.findRegion("playerForward");
TextureRegion playerBackTR = myTextures.findRegion("playerBack");
TextureRegion playerSideTR = myTextures.findRegion("playerSide");

Just using the texturepacker, the findRegion will match the original filenames, so for example, before I packed it, it was "playerForward.png"


Then you can just apply your TR the same way as you would textures,  to your sprites/buttons or whatever

"Experience is what you get when you did not get what you wanted"
Offline davedes
« Reply #5 - Posted 2013-08-29 14:45:50 »

From some more poking I'm getting 40 batches per frame, which doesn't sound like a lot but could be part of the problem.

This seems to be causing a draw batch for every button since the nine patch and text use different textures. Is there a way to layer these at runtime via sprite batch (so all text is drawn over the top), or do I need to start merging the textures into an atlas somehow?

Also I can't see how I'd avoid having two batches if I want to draw the fps text separately. Stage doesn't expose the sprite batch. I guess I could add an Actor for the fps but that seems like a sledgehammer to crack a nut.
40 batches sounds like a lot for simple menu UI on mobile. Think more along the lines of 4 or 5... Tongue

When creating a Stage, pass the shared SpriteBatch as the last constructor.

It probably won't be easy to re-order the draw calls and still keep the utility of an Actor (position etc). Maybe this could be achieved with z-index, which changes the sort value of the actor. 

TexturePacker GUI is pretty useful for texture packing; or TexturePacker2 if you'd rather work with a command-line utility. There is also PixmapPacker which is good during development:
http://www.badlogicgames.com/wordpress/?p=2297

Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #6 - Posted 2013-08-30 00:42:31 »

Hmm. Packing the couple of textures and font at runtime means I've now got my 40-odd sprites and text being drawn in one batch, so that's good - however in-game with a small tile map I'm still only seeing 20-25fps (which is an improvement, but far from 60fps). And DDMS says I'm still taking 20ms for 'Process' per frame.

Needs more probing...

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Grunnt

JGO Wizard


Medals: 55
Projects: 9
Exp: 5 years


Complex != complicated


« Reply #7 - Posted 2013-08-30 10:15:07 »

Really weird, I get better performance than what you describe on a pretty ancient HTC Hero test device. Do you have any code to show?

Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #8 - Posted 2013-08-30 12:22:35 »

It does feel like there's something else going on I'm missing. Next step is to strip back the code to the bare minimum and see how performance changes (if at all).

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #9 - Posted 2013-08-31 16:57:36 »

Aha! Looks like the code is fine - it's actually the debugger (more specifically, DDMS) that's causing the drop. Running the app from the device gets 60fps, but if I then get DDMS to connect to that process the framerate drops to 20ms. Shutting down eclipse (and thus DDMS) makes the performance shoot back up to 60fps.

It looks like this old (and still open) bug from 2011: https://code.google.com/p/android/issues/detail?id=21190

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Cero
« Reply #10 - Posted 2013-08-31 18:12:54 »

ah that would explain it. I only use logcat.
I mean with libgdx you can just develop entirely on pc, debugging, profiling everything.
I only occasionally push to device. Its only really interesting for touch specifics, dpi/ppi stuff / screensize and thats about it.
Which is one of the great point about libgdx =D

Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #11 - Posted 2013-08-31 19:08:05 »

ah that would explain it. I only use logcat.

I'm not sure that's true; DDMS seems to be a required part of the debugger backend - you're using it even if you're not using the DDMS perspective in eclipse.

I'm not entirely convinced I've got all the problems out though - I'm still seeing very spiking framerate behaviour even without DDMS. I don't know if this is standard for android and getting a smooth 60fps is impossible?

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Cero
« Reply #12 - Posted 2013-08-31 22:02:16 »

ah that would explain it. I only use logcat.

I'm not sure that's true; DDMS seems to be a required part of the debugger backend - you're using it even if you're not using the DDMS perspective in eclipse.
Yeah I also thought that was the case... Never had any problems thats I know of...

I'm not entirely convinced I've got all the problems out though - I'm still seeing very spiking framerate behaviour even without DDMS. I don't know if this is standard for android and getting a smooth 60fps is impossible?
Well its very easy on my galaxy S3, maybe you should post your whole code or whatever, shrunk down to bare minimum where the problem still persists.
But yeah 40 batches per frame are bad. It should be 2-6 or whatever

Offline Phibedy

Senior Member


Medals: 8



« Reply #13 - Posted 2013-10-15 23:12:53 »

There is a huge performance issue if you use ddms, normally our game has 60 fps, with debugger 10-30.
on android you should care about the texture you bind and how often you bind it. Put all textures which are rendered in one step in one atlas-sheet.
Your atlas shouldn't be bigger than 1024x1024, otherwise "old" mobiles can't bind it.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (52 views)
2014-04-15 18:08:23

BurntPizza (49 views)
2014-04-15 03:46:01

UprightPath (64 views)
2014-04-14 17:39:50

UprightPath (46 views)
2014-04-14 17:35:47

Porlus (63 views)
2014-04-14 15:48:38

tom_mai78101 (88 views)
2014-04-10 04:04:31

BurntPizza (147 views)
2014-04-08 23:06:04

tom_mai78101 (244 views)
2014-04-05 13:34:39

trollwarrior1 (203 views)
2014-04-04 12:06:45

CJLetsGame (210 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!