Not logged inGosu Forums
Forum back to Help Search Register Login
Up Topic Gosu / Gosu Exchange / High CPU usage
- - By Jwosty Date 2011-07-16 17:42
Okay. I am making a game that has to display potentially hundreds of images at once, some which are offscreen. I noticed that it was lagging a bit (poor Gosu, having to display so much... stuff), so I opened activity monitor (A Mac application that displays information about each process running on your comp) and ran my game at the same time. Here are a few samples (I averaged the CPU usage and Threads; some keep changing on me :P):

Process Name          % CPU          Threads

Activity Monitor         1.0                3
Finder                       0.0                5
Google Chrome         0.4                23
iTunes                      1.5                25     (I was listening to music when i posted this, so... yeah)
Terminal                   0.0                5
TextWrangler            0.0                4

And then my game:

Process Name          % CPU          Threads

ruby                          95                 3

Any ideas on how to bring it down? I don't want to melt my nice iMac xP
Parent - - By lol_o2 Date 2011-07-16 18:39
Maybe use clip_to method? It possibly can save some CPU by skipping offscreen images.
Parent - By Jwosty Date 2011-07-17 00:29
Okay, I'll try that. Thanks!
Parent - - By jlnr (dev) Date 2011-07-16 19:14
You should structure your game in a way so that you can efficiently draw only those objects that are on screen. For example, if you have a tiled map, you should loop from the first visible tile in the top left corner of the screen to the lower right corner of the screen, not from 0..width, 0..height.
I think some other people have used spatial hashes for objects that are not aligned on a grid.

With any optimization in Ruby you should be aware that the actual drawing in Gosu is likely very cheap, Gosu can easily draw hundreds or thousands of images in C++. However, every Ruby method call, loop etc. is very costly because Ruby is slow. Try to keep things simple where possible.
Parent - - By Jwosty Date 2011-07-17 00:35
Yeah, it is a tiled map. It's funny really, it even lags a touch when the map is 25x25 tiles (each tile being 40x40 pixels) with the origin of the map being 0, so all the images start onscreen. It's a scroller so the images can be offscreen.

I'm using this line of code to draw each tile:

@tiles.each {|tile| tile.draw}

Do you know if there is any way to speed this up? Adding a conditional would likely slow it down some more.

I'll do some research on this.
Parent - - By lol_o2 Date 2011-07-17 07:05
Conditional won't slow this. In my game I'm using 4 conditions to compare the tile position with screen position, so offscreen tiles are not drawn. And it's working much faster than drawing everything.
Parent - By Jwosty Date 2011-07-17 20:19
Oh, okay!
Parent - - By Spooner Date 2011-07-17 13:27
Drawing 25x25 tiles should not cause you any pain at all. I suspect that it isn't the tile drawing that is slowing the whole thing down. Consider trying ruby -rprofile mygame.rb to profile your game and see what is really sucking up your time.

Also, check Window#fps, since that is more useful a measure of how slow your code is really going, rather than the CPU %. I suspect it would be running at 60FPS even if you were drawing a lot more tiles than that. Still, it is worthwhile only drawing the tiles that are on-screen and the logic to do this will be faster than the unnecessary drawing actions if you draw everything.
Parent - - By Jwosty Date 2011-07-17 20:21
Sure that makes sense. I think I will have an array of onscreen tiles, so that only they will draw.

What does profile do?

Alarmingly, it went down to 18 FSP! :O
Parent - - By Spooner Date 2011-07-17 21:12
Oh, after you close the application again, it will give you a readout of what methods took what amount of time. Can be useful for finding bottlenecks in your code, but isn't always very helpful (just a suggestion, anyway). Running a Ruby program using Profile will greatly slow down your application since it does a lot of benchmarking in the background (it isn't going to speed it up, it tells you what is slow so you can try to optimise it).
Parent - By Jwosty Date 2011-07-18 13:59
Ah, okay. I think I know what is slowing it down anyway, it is a draw loop that looks like this:

@tiles.each {|tile| tiles.draw}

And @tiles can contain thousands of objects. At 25x25 (625) tiles, it does fine. That fills up one screen full of tiles. But I tested it at 75x75 (5,625), and that's when it starts to lag. And I plan on it being able to have MUCH more than that.
Parent - - By Jwosty Date 2011-07-18 13:59
I think I have a solution anyway
Parent - - By kaBOOM Date 2011-07-25 15:48 Edited 2011-07-25 15:54
try somethin like this:

for i in @tiles
#next if i.screen_x < 0
#next if i.screen_x > screen_width

Now, the tricky part is figuring out the tiles 'screen_x' and 'screen_y' values.

You should try using a hash, like this:

@tiles = {}[x,y], value)

This way finding out the screen_x and screen_y of the tiles is much easier.
Parent - By Trebor777 Date 2011-07-26 11:07
just a tiny adjustement to that bit of code
it's :
i.screen_x < - i.width    :) because you want the full tile to be off screen :) not just one of is corner.
i.screen_y < -i.height
Up Topic Gosu / Gosu Exchange / High CPU usage

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill