how to make game consume less cpu/gpu resource

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By fliar
:warning: Old Version Published before Godot 3 was released.

even a simple mine-sweeping game will make the fan roar, cpu usage is pretty high, is there a way to fix it?

my monitor shows godot editor uses 10% cpu, and the game uses 18% constantly, so my laptop becomes hot quickly

the game I created is just a simple mine-sweeping game (30x16 grids)

so it has about 480 buttons, with onclick event connected and that’s it, no update code for each frame, at least I didn’t implement any update code

it is pretty high cpu usage for me
what is more, recently I found that when the game is minimized for a while, the Godot editor console shows the game is running at about 500 fps, and the cpu usage reached 98%, which made me more confused

it doesn’t happen to me, it happens when you run games made with godot or other game too?

Phil88n | 2017-06-21 09:33

Is your framerate capped/vsync on?

Zylann | 2017-06-21 10:01

@Phil88n yes, my monitor shows godot editor uses 10% cpu, and the game uses 18% constantly, so my laptop becomes hot quickly
@Zylann I haven’t change these settings, they should be default config

fliar | 2017-06-22 07:01

Is your laptop having two graphic cards? (and if yes, are you running Godot on the better one? some laptops have this dual config to save power)
Are there any special messages printing in the console?
Also what is your config? Os, graphics card, laptop model…

Zylann | 2017-06-22 13:01

@Zylann no, it’s an integrated intel graphic card, my laptop is a MacBook Pro 13 2016 without touchbar, the console prints fps only, usually 60, or about 500 when minimized

the game is simple too, only buttons and labels are used

fliar | 2017-06-25 03:32

If it prints 500 fps that means you didn’t cap the FPS, and then the game tries to run as fast as it can, consuming more CPU. Try to make sure FPS is capped at 60 or enable V-sync and see if it changes anything.

Zylann | 2017-06-25 15:31

:bust_in_silhouette: Reply From: rredesigns

I’m sure there is. 18% doesn’t seem like a lot of load anyway, if your game is finished, then export it so you won’t have the editor running at the same time. If not, then try to improve your code.

If you have mostly static bodies, then there must be a lot of unnecessary code running each frame, so optimization on your side will be needed as well.

In the end, it all depends on the game itself, and untill we can get to see your code there’s not much we can say about it. I guess you could use more than one core too (Godot uses only one for safety), to split the load on other core and reduce heat that way, the option is located under the project preferences section.

thanks for the answer , I’ll edit my question to make it more clear:

the game I created is just a simple mine-sweeping game (30x16 grids)

so it has about 480 buttons, with onclick event connected and that’s it, no update code for each frame, at least I didn’t implement any update code

it is pretty high cpu usage for me
what is more, recently I found that when the game is minimized for a while, the Godot editor console shows the game is running at about 500 fps, and the cpu usage reached 98%, which made me more confused

fliar | 2017-06-25 03:23

The game should never run higher than 60fps, there’s a lock for that. Unless of course you unchecked it.

Also. What kind of game ever needs that humongous ammount of buttons? Would that even fit a screen? If that’s actually the case, then you need a ton of CPU and GPU to draw al that. Your only option is to put less things on screen and in memory.

rredesigns | 2017-06-25 03:26

@rredesigns when it’s normal, yes the fps is 60, but when the game window minimized, it seems that there’s no lock for that

fliar | 2017-06-25 03:34

Then I suggest you open an issue on Github, this can be a serious bug. :slight_smile:

rredesigns | 2017-06-25 03:36

for a mine sweeping game, each grid is a button right?

fliar | 2017-06-25 03:45

Buttons are not exactly cheap to render. Why don’t you try animated sprites instead. Each click that node will go one frame further. Depending on the type of node it is, that will be either a mine or something.

I suppose for those which are not mines the second frame will be transparent (or directly hide the node) and let see the number below, or place a label under it, I don’t know, there are plenty of alternatives. Buttons I would say are not the best, definitely.

I don’t know the internals of buttons or the engine at a deep level, but just consider the ammount of properties control nodes have. They surely take up more space in memory per node than others.

To sum up, my recommendation: Use sprites and a tilemap. :slight_smile:

rredesigns | 2017-06-25 03:49

I would definitely use a TileMap for this kind of game. A single button handles a lot of things and isn’t great at displaying hundreds of them, while a TileMap is highly optimized to display lots of sprites in a grid.

Zylann | 2017-06-25 15:34

so button consumes a lot of cpu resource ? didn’t expect this
I thought button is updated only when pressed or cursor in/out, not every frame

I’ll try the TileMap thing later

fliar | 2017-07-01 03:04

And you were partially right. They do have callbacks for when they receive inputs. The thing is that they also need a listener to wait for that input to happen, and that runs every frame.

rredesigns | 2017-07-01 03:07

I don’t think listeners should be updated per frame, if this is true, maybe every scene with 480 nodes connected with custom callbacks will suffer performance issue

fliar | 2017-07-01 03:20

They should, and they are. What happens if you only update some frames? Will you just miss the input that happened in not listened frames? That would be the actuall issue, a missed input signal.

Buttons work as they should, they are buttons for a reason, and they always expect input, they listen for it and they do it as often as possible so they won’t miss a click. Does that make sense? It does to me.

Nevertheless, you are not supposed to use them that way, that’s for sure. And if you have one big tilemap instead of 400 buttons waiting for input you would have reduced the cpu load by at least 95% (in that job alone, the rest remains the same). :wink:

rredesigns | 2017-07-01 03:26

IMHO, listeners should work like this: when there’s an input, the listener calls the button to work, when there’s no input, listener does nothing, so the no-input frame could be skipped for listener to handle

fliar | 2017-07-01 06:43

And how would you know “when there’s an input”? That’s what the listeners are for, to detect the input.

There’s no magic here. The listener is what detects the input event, and in order to catch all of them it runs every frame. If there’s no listener running all the time, no input events can be detected.

rredesigns | 2017-07-01 13:07

I mean, there IS something to detect input per frame. if it is done by listener, let’s say it’s a primary listener. so it should work like this, taking ‘button press’ as an example:
when there’s a button press event, this primary listener captures this event, then find out which button is pressed, and dispatch this event to the corresponding button. if the primary listener detects no button press event, the procedure stops 'cause there’s no need to check which button is pressed, in this case the number of buttons will not use cpu, they are skipped right?
in my case, it looks like even I’m doing nothing, the game is consuming the cpu resource all the time, and much more even if it is minimized.

fliar | 2017-07-01 13:41

“…there IS something to detect input per frame…” - Good. You know that then.

“…when there’s a button press event, this primary listener captures this event, then find out which button is pressed…” - To know which control node has received input, each node has to be checked. I told you, there’s no magic in here.

“…dispatch this event to the corresponding button…” - Per-button checks are needed periodically for this in order to be efficient. Otherwise you would get great delay.

“…listener detects no button press event…” - That doesn’t exist. Only events can be detected. You can’t detect something that didn’t happen (like no-event), but if you want to get a return when there’s no input you still have to check every frame.

“…cause there’s no need to check which button is pressed…” - Buttons are expected to be pressed frecuently, that’s their nature and they exist only to be pressed. They must be checked no matter of what.

“…even I’m doing nothing, the game is consuming the cpu…” - The fact that you are not generating input doesn’t mean the main loop stops checking for it.

I think you are failing to understand how input detection works. Perhaps you say “well, when a click is computed go check where it happened, then check what node is in that position, then see if it has any logic and deliver the input”.

But that is incredibly inefficient. It would take so much time to do all that, and definitely a lot more processing time.

Each control node detects on itself. So if any input is detected the node knows right away what event just happened. And that is how is supposed to work.

Still, you can use the TileMap to do what you are saying here. Put an area 2D on top of it, then detect the input, then check the coordinates, then try to guess what tile is under that position. You CAN’T make Control nodes work that way, unless of course you fork the engine and modify the source to do that.

rredesigns | 2017-07-01 13:53

good, so the primary problem is the number of nodes, I should do a test on that

fliar | 2017-07-01 23:35

No, but rather the type of node. You can’t do anything with any node, each has a purpose, and serve that purpose very well.

You can use buttons of course, you actually are using them right now, but that’s not the most efficient approach as you might have noticed.

rredesigns | 2017-07-01 23:54

:bust_in_silhouette: Reply From: bootyman

With so many buttons there’s no wonder the performance is terrible, what i recommend you doing is having the tilemap as grid and have “buttons” as tiles, then when the user clicks on the tilemap, just calculate which tile he clicked based on position of the tilemap and the position of the mouse, then get the tile, do your logic, replace the tile. With your method you checked for 480 button clicks each frame, with this method you only do one.

I’ll pick this as solution, though I haven’t try this yet, but this is also suggested by @rredesigns and @Zylann
thank you, but I don’t know how to give credits to you, thanks for the comments again

fliar | 2017-07-01 03:12

:bust_in_silhouette: Reply From: fliar

finally i got another solution to this problem, and I think this should be the best answer:

in OS — Godot Engine (stable) documentation in English

void set_low_processor_usage_mode ( bool enable )

Set to true to enable the low cpu usage mode. In this mode, the screen only redraws when there are changes, and a considerable sleep time is inserted between frames. This way, editors using the engine UI only use very little cpu.

now my mine-sweep game consumes 1.x% cpu, I think this is it

This option does not work for mobile devices.
It’s not implemented for it.

volzhs | 2017-07-19 08:26

So is there no drawback on using this mode? Like slight delay on Input/Change on Screen. And not working on mobile? That would be a shame … would be an awesome feature to save battery time on mobile.

Adolar | 2018-02-20 16:13