Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Question about optimizing in SFML  (Read 6536 times)

0 Members and 1 Guest are viewing this topic.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Question about optimizing in SFML
« Reply #15 on: June 08, 2011, 12:10:06 am »
Quote from: "Laurent"
We're not gods
I am! :D j/k

Anyway what changes have you done since last? Since it wasn't that bad when I tried it for you? You could have several zombies on without any lag(staying around 60FPS).

Also the drawing is not the culprit here. (It might be a bit on tiles but not when it come to entities) so I would guess somewhere in your logic.

A very simple and probably one of the best debugging tests is what Laurent suggests. IF you think drawing is the culprit, just comment out THAT line and nothing more and see what happens. Does the FPS go up significantly? No then the problem is somewhere else and I think it's in your logic, especially since you got pixel collision. It is generally slow, there are tricks to speed it up but compared to other tests it is really slow. (Imagine a 16x16 image using a AABB test versus pixel test. Either we have 4 comparisons or we have 256 if it's a primitive version)
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #16 on: June 08, 2011, 12:17:15 am »
Quote from: "Groogy"
Quote from: "Laurent"
We're not gods
I am! :D j/k

Anyway what changes have you done since last? Since it wasn't that bad when I tried it for you? You could have several zombies on without any lag(staying around 60FPS).

Also the drawing is not the culprit here. (It might be a bit on tiles but not when it come to entities) so I would guess somewhere in your logic.

A very simple and probably one of the best debugging tests is what Laurent suggests. IF you think drawing is the culprit, just comment out THAT line and nothing more and see what happens. Does the FPS go up significantly? No then the problem is somewhere else and I think it's in your logic, especially since you got pixel collision. It is generally slow, there are tricks to speed it up but compared to other tests it is really slow. (Imagine a 16x16 image using a AABB test versus pixel test. Either we have 4 comparisons or we have 256 if it's a primitive version)



Well the problem seems to come within the for loops, which is to be expected.

once we removed PixelCollision and replaced with rectangular collision, it was a bit faster.

but we're not sure how to optimize for loops exactly...

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Question about optimizing in SFML
« Reply #17 on: June 08, 2011, 01:46:33 am »
It's kinda hard to help you over the forum like this since you have problem giving us more precise information. Also you seem to be in a different timezone. I should be sleeping now ^^

Did you gain anything major by commenting out the Draw call?

How large is the world? How do you cull the tiles from being updated/tested against/rendered?

If you do a test against each tile in the world if it is shown that might be your villain.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #18 on: June 08, 2011, 02:16:51 am »
Quote from: "Groogy"
It's kinda hard to help you over the forum like this since you have problem giving us more precise information. Also you seem to be in a different timezone. I should be sleeping now ^^

Did you gain anything major by commenting out the Draw call?

How large is the world? How do you cull the tiles from being updated/tested against/rendered?

If you do a test against each tile in the world if it is shown that might be your villain.


If the tile intersects the view (window) it's drawn.
however if I comment our draw line for TILES, I get 130 fps vs, 50.

Zombies are now fine. But Tiles are my issue...

World is (192x192)x64 now. (64 being width/height of tile)

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Question about optimizing in SFML
« Reply #19 on: June 08, 2011, 12:45:45 pm »
That means that you do test against each tile in the world? Try with this, implement a grid where each cell is as big as one screen. And then before checking against the tile you first check "What cell's are currently in view(A maximum of 4 can be seen in worst case scenario) and then you go into these cells and test against the tiles inside the cell.

Pseudo code:
Code: [Select]

for each cell in grid
{
        if( view.rect.intersects( cell.rect ) == true )
        {
                for each tile in cell
                {
                        if( view.rect.intersects( tile.rect ) == true )
                        {
                                window.draw( tile )
                        }
                }
        }
}


With this you will cut away a lot of tiles by effectively ignoring cells that is not inside the view.
This can also be used for cutting away impossible collision tests as you only need to test against the objects placed in the same cell or the neighbor cells.

Just gonna try some example math here. Let's say we have what you said, 192 x 192 tiles of the size 64. That means we got a total of 36864 tests to see if it is shown or not. Let's assume we have a 800x600 screen then only about 10x10 tiles are visible at the same time. But we still do 36864 tests to see if we can see them. With a grid we will arrange so we have 10x10 tiles in each grid cell. So that means we have 369 cells over our map. So now instead to find the tiles that can be shown we do 369 tests for see what cell is shown and 100x(the amount of cells shown,1-4) tests against the tiles to see what to draw. So instead of doing 36864 tests we have reduced it to 369 + 100 x (1-4). So worst case scenario is 769 tests.

NOTE: I might have done some numbers wrong but the fact stands that you do cut away a lot just by adding a higher hierarchy grid to test against. Depending on how your logic is you might need to tweak some things(like size of cells and so on) in order to get most optimal performance gain from it.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Svenstaro

  • Full Member
  • ***
  • Posts: 222
    • View Profile
Question about optimizing in SFML
« Reply #20 on: June 08, 2011, 05:43:53 pm »
Currently you only seem to be poking around. Why not actually profile your code?

Get valgrind and kcachegrind. Assuming your binary is called "zombies", do this:
Code: [Select]
valgrind --tool=callgrind --callgrind-out-file=zombies.callgrind ./zombies
This will run your game in a virtual CPU and record all function calls and see how long they will take. It also records API calls and everything. It will be very slow but don't worry, it will not produce false results.
Then use kcachegrind to visualize all this in an easy and colorful browser:
Code: [Select]
kcachegrind zombies.callgrind

This should get you a whole lot farther than any amount of guessing will.

EDIT: It will look something like this. Pay attention to the "self" bar which show you how long a function will take by itself.

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #21 on: June 08, 2011, 07:09:34 pm »
Quote from: "Groogy"
That means that you do test against each tile in the world? Try with this, implement a grid where each cell is as big as one screen. And then before checking against the tile you first check "What cell's are currently in view(A maximum of 4 can be seen in worst case scenario) and then you go into these cells and test against the tiles inside the cell.

Pseudo code:
Code: [Select]

for each cell in grid
{
        if( view.rect.intersects( cell.rect ) == true )
        {
                for each tile in cell
                {
                        if( view.rect.intersects( tile.rect ) == true )
                        {
                                window.draw( tile )
                        }
                }
        }
}


With this you will cut away a lot of tiles by effectively ignoring cells that is not inside the view.
This can also be used for cutting away impossible collision tests as you only need to test against the objects placed in the same cell or the neighbor cells.

Just gonna try some example math here. Let's say we have what you said, 192 x 192 tiles of the size 64. That means we got a total of 36864 tests to see if it is shown or not. Let's assume we have a 800x600 screen then only about 10x10 tiles are visible at the same time. But we still do 36864 tests to see if we can see them. With a grid we will arrange so we have 10x10 tiles in each grid cell. So that means we have 369 cells over our map. So now instead to find the tiles that can be shown we do 369 tests for see what cell is shown and 100x(the amount of cells shown,1-4) tests against the tiles to see what to draw. So instead of doing 36864 tests we have reduced it to 369 + 100 x (1-4). So worst case scenario is 769 tests.

NOTE: I might have done some numbers wrong but the fact stands that you do cut away a lot just by adding a higher hierarchy grid to test against. Depending on how your logic is you might need to tweak some things(like size of cells and so on) in order to get most optimal performance gain from it.


Very nice idea, we'll definitely look into it and incorporate it in the future!

Quote from: "Svenstaro"
Currently you only seem to be poking around. Why not actually profile your code?

Get valgrind and kcachegrind. Assuming your binary is called "zombies", do this:
Code: [Select]
valgrind --tool=callgrind --callgrind-out-file=zombies.callgrind ./zombies
This will run your game in a virtual CPU and record all function calls and see how long they will take. It also records API calls and everything. It will be very slow but don't worry, it will not produce false results.
Then use kcachegrind to visualize all this in an easy and colorful browser:
Code: [Select]
kcachegrind zombies.callgrind

This should get you a whole lot farther than any amount of guessing will.

EDIT: It will look something like this. Pay attention to the "self" bar which show you how long a function will take by itself.


I've been profiling our code alot actually, it's just so vague because it spends it's time in update/drawing, and I don't have enough specific functions just yet but thanks for the help.

P.S. you guys are awesome as always ^^