SFML community forums

Help => Graphics => Topic started by: Glocke on May 25, 2016, 12:35:15 pm

Title: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 12:35:15 pm
Hi, I'm aware of the existence of LTBL ^^
Atm I'm working on the overall performance of my RPG - its current bottleneck is my lighting implementation. That's why I cut it out to a minimal example. The code can be found on https://github.com/cgloeckner/sfml-lighting-test

On my laptop (Intel i7, GeForce GT 540M using NVIDIA binary driver 352.63 @ Ubuntu wily - btw other drivers cause major problems) the example code runs with
I guess this is an issue related to my implementation. Got anybody an idea how I can find the bottleneck?

About the code: I seperated "light", "shadow" and "fog" layers because of my rendering order:
Maybe there even are ways to improve this :)

Thanks in advance!! :)
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 12:47:28 pm
Quote
Got anybody an idea how I can find the bottleneck?
Use a profiler. If it reveals that the bottleneck is on the OpenGL side (which is likely), then I'm pretty sure you can find an OpenGL profiler to go further.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 01:14:28 pm
Use a profiler.
Good point! Unfortunately I don't have much experience reading profiler output :S

I added some of the top lines from the output to the spoiler btw. I just understand that the Vector::operator- and my getFarPoint() and update() use most of the time. :-[ What should I be able to read from this?

(click to show/hide)
Title: Re: Performance on Drawing Lightened Scene
Post by: Hiura on May 25, 2016, 01:25:37 pm
Good point! Unfortunately I don't have much experience reading profiler output :S

Then you might love this: https://github.com/jrfonseca/gprof2dot It's really an intuitive visualisation I think. There're also some nice tips'n'tricks on compiler's option.
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 02:16:26 pm
First, you should let the profiler run for more than 30 ms (typically a few seconds minimum). The longer it runs, the more samples it collects, and the more accurate it is.

Then there's nothing more complicated than what you've read: the 3 first entries take all the time, at equal part.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 02:40:18 pm
First, you should let the profiler run for more than 30 ms (typically a few seconds minimum). The longer it runs, the more samples it collects, and the more accurate it is.

Then there's nothing more complicated than what you've read: the 3 first entries take all the time, at equal part.

I re-ran it with lots of edges and lights (for ~30s, because of the low framerate) and for few edges and lights (for 6-7s).

lots of edges and lights
(click to show/hide)

few edges and lights
(click to show/hide)

Based on those results I can only come to the conclusion, that the update() method is the bottleneck (lol, cpt. obvious xD). How to go more into detail?
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 02:47:43 pm
Do you run a debug or an optimized build of your application? It's strange that sf::Vector2 operators take so much time. They should even be inlined in optimized builds, an not appear at all in the profiler's output.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 02:54:22 pm
Do you run a debug or an optimized build of your application? It's strange that sf::Vector2 operators take so much time. They should even be inlined in optimized builds, an not appear at all in the profiler's output.
I was using
g++ -o main main.cpp lighting.cpp -I./ -lsfml-system -lsfml-window -lsfml-graphics -std=c++11 -g -pg
 
for building, so it's a typical debug one I think.
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 03:59:57 pm
There's no point measuring performances with a debug build.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 04:08:18 pm
Profiling an optimized build results doesn't give me a hint neither :S
(click to show/hide)

/EDIT: Less aggressive optimization ... ok could be "getFarPoint" ... but ... well ... ^^
(click to show/hide)
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 04:13:20 pm
You can subdivide big functions into several smaller ones if you want to get more detailed profiler results.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 04:23:56 pm
You can subdivide big functions into several smaller ones if you want to get more detailed profiler results.

This gives me (with less aggressive optimization):
(click to show/hide)

So to say: getFarPoint() is my bottleneck?
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 04:31:18 pm
For sure ;)
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 04:35:44 pm
For sure ;)
Ok but why? The code is:
sf::Vector2f getFarPoint(sf::Vector2f const& origin, sf::Vector2f const & pos, sf::FloatRect const& box) {
        // calculate normalized direction
        auto direction = pos - origin;
        auto norm = std::sqrt(direction.x * direction.x + direction.y * direction.y);
        direction /= norm;
        // calculate suitable distance
        auto dist = box.width * box.height;
        // create far point
        return pos + dist * direction;
}
I'd assume the calculation of the square root as most expensive .. floating point division could be expensive, too ... could. I don't know how to optimize at this point? Any ideas? :)
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 25, 2016, 05:30:21 pm
Well it's not the implementation itself, it's more the algorithm that calls it way too much. I'd say you should focus on optimizing your algorithm rather than the code itself.
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 25, 2016, 05:48:30 pm
Ok, makes sense :) But to be honest, I'm unsure how I could optimize the algorithmic approach.. maybe using some additional culling to determine which edges are really hit by a light's ray... 8)
Title: Re: Performance on Drawing Lightened Scene
Post by: Hapax on May 25, 2016, 10:03:53 pm
Where is that extra 0.1% of time coming from? (They keep adding up to 100.1%)
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 27, 2016, 08:13:12 am
Where is that extra 0.1% of time coming from? (They keep adding up to 100.1%)
I guess its up to some rounding issue.

I reran the profiling analysis for few edges and many lights:
(click to show/hide)
Does this mean that there is no bottleneck in this case?
Title: AW: Performance on Drawing Lightened Scene
Post by: eXpl0it3r on May 27, 2016, 05:11:54 pm
Well think about it. Do you need to call prepareLight or getFarPoint 7200 times per (not sure how long that was sampled over)?
Title: Re: AW: Performance on Drawing Lightened Scene
Post by: Glocke on May 27, 2016, 05:20:33 pm
Well think about it. Do you need to call prepareLight or getFarPoint 7200 times per (not sure how long that was sampled over)?
prepareLight() is called twice per light per frame (could be reduced to once maybe). But calling it once is minimum because I don't want to have one sprite per light.. it's unnecessary from my point of view.
getFarPoint() is called once each pair of lights and edges, because each light could hit each edge. As mentioned: num_lights x num_edges is just an upper bound and not necessary in each case. I think that's the best way to go for me atm.
Title: Re: Performance on Drawing Lightened Scene
Post by: Laurent on May 27, 2016, 05:40:40 pm
Yes, if not already done, you should use space partitionning to limit useless computations (edges not in range of lights, for example).
Title: Re: Performance on Drawing Lightened Scene
Post by: Glocke on May 27, 2016, 05:44:22 pm
Yes, if not already done, you should use space partitionning to limit useless computations (edges not in range of lights, for example).
Thx, but this is already done :) Except not culling edges that are hidden by other edges but still visible in the scene.

But anyway: My problem also occures if I have lots of lights and few edges .. extreme case: 50 lights and 1 edge (assuming space partitioning is already applied). Then getFarPoint() will be called 50x (like 1 Light and 50 Edges which runs perfectly fine). The profiler tells me nothing (see spoiler above).