Vinatorul / minesweeper-rs

Simple minesweeper in Rust
MIT License
76 stars 9 forks source link

Process should be almost idle but the CPU load is 66%. #22

Closed getreu closed 9 years ago

getreu commented 9 years ago

Process should be almost idle at the end of the game, but the CPU load is 66%. !

Vinatorul commented 9 years ago

Thank you for report! Can you check it now?

getreu commented 9 years ago

Unfortunately no change. Good news: the bug is easy to reproduce: just loose :)

Vinatorul commented 9 years ago

I thought it was a problem with fps. Ok, I'll try fix it when come home. Btw, what happens when you restart the game, still heavy load cpu? Can you try to set fps to 30, 15, 10 and check?

getreu commented 9 years ago

Actually. I observed the same CPU load after starting (see screenshot).

Vinatorul commented 9 years ago

I checked it on various fps and found correlation between it and cpu usage.

xilec commented 9 years ago

I suppose, the problem in piston implementation itself. For instance, Piston redraw all widgets on window all time earlier. A few last versions they implemented some improvements in usage of cpu. IMHO, we should move to last piston version to improve it.

Vinatorul commented 9 years ago

This is good idea, I will try do it tonight. Hope there weren't much breaking changes.

xilec commented 9 years ago

On my configuration, I have 7% load cpu by default and it increase to 14% if I set field size 50x50 cells. It seems that redrawing of field requires too much cpu time. If I comment line

    self.field.draw(c, g, field_rect, &mut self.glyphs);

in method Game::render then cpu load decrease to 1.5%

Vinatorul commented 9 years ago

I know that it is redrawing:

I checked it on various fps and found correlation between it and cpu usage.

The question is - can we fix it, or not?

I have an idea - to change game to event driven. Redraw only if something happened, it will solve the problem, but we will be unable to draw animation if we, may be, want it in future. I will try it on this weekend

xilec commented 9 years ago

@Vinatorul, wait. There is a hope that this approach give us enough performance results now and ability to draw pictures and animations in future. I try to do it at the weekend.

xilec commented 9 years ago

My attempt is fail. I tried to make prerendered cells in sprites of scene. Unfortunately, I didn't find any API for render text in textures or images and so that I just prerender rectangles for cells and draw it by scene-object. It didn't get any valuable effect and cpu load stay almost the same. If ellimate drawing of numbers cpu load became less around 10% from original cpu load. It seems to me that big part of cpu load is copying of pixels for drawing.

Vinatorul commented 9 years ago

@xilec I think event-driven solution will be suitable for such game

xilec commented 9 years ago

@Vinatorul Definetly, event-driven approach is the most efficient solution for this game, but how do you want achieve this. As I understand Piston don't give such option. At least, when i tried to not redraw picture, if user don't execute any input, it start blinking. I had another option: draw whole window(or fragments) of it into buffer (or small buffers, that is should be more efficent) and so that eliminate cpu load overhead (because we should render only 1 time changed part of picture in buffer) and pass this prerendered buffer to gpu for drawing by some fast commands of copying. But also I didn't see this API in Piston (especially interesting about drawing text in buffer)

getreu commented 9 years ago

Any news here?

Vinatorul commented 9 years ago

Unfortunately, still no ideas.

xilec commented 9 years ago

When I tried naive redrawing only when user do some input, window started blinking because inside the piston event loop implemented double buffering approach and I redraw just 1 buffer. Now, when picture is redrawn on both buffer, window picture looks good without such cpu load.

getreu commented 9 years ago

Works for me! :) The load dropped from approx. 90% to 5%. Just for my understanding: what 2 buffers you have to redraw?

xilec commented 9 years ago

@getreu look into chapter "Double buffering in computer graphics" on this wiki page. The same approach is used in implementation of PistonWindow. Method PistonWindow::draw2d() doesn't draw directly on the screen. It draws on back buffer of window while we seeing on another buffer, that is shown on the screen. After each iteration of event loop, these buffers are swaped and we see what we had drawn on previous iteration and we can draw on another buffer. If we don't draw in buffer on current iteration of event loop, buffers are swaped any way. If we don't know it and trying draw changes only on the iteration, when they happen, we get 2 different pictures on 2 buffers (for instace: picture with first screen picture of minesweeper and solid black) which is swapping on each iteration of event loop. That's why I got blinking in naive try when just skip redrawing picture if never happen with user input. I hope I clear up a situation with double buffering.

getreu commented 9 years ago

@xilec I got the point. If I understood right the employed technique here is Page flipping. Thank you for your detailed explanation.