SuperTux / supertux

SuperTux source code
https://supertux.org
GNU General Public License v3.0
2.47k stars 471 forks source link

Having many PulsingLight game objects makes SuperTux slow #1300

Open HybridDog opened 4 years ago

HybridDog commented 4 years ago

SuperTux version: 0.6.1 System information: Lubuntu 18.04

Expected behavior

The presence of many game objects should not significantly slow down the game.

Actual behavior

In the old tower_of_ghosts.stl, there were lots of redundant lava tiles. A PulsingLight game object is added for every lava tile; disabling its draw function or reducing the window resolution did not increase the framerate, so the lag is not caused by rendering. In that level, when the lava tilemap is not removed, there are ca. 2400 game objects (probably mostly PulsingLights); in another level there are only 240 game objects. Maybe SuperTux is very slow when there are many game objects.

The get_objects_by_type method in the GameObjectManager class iterates through all game objects and uses dynamic_cast to find only specific game objects. Maybe this method is invoked very often and causes a bottleneck; I do not know how to test it without much effort.

Steps to reproduce actual behavior

This old tower_of_ghosts.stl level is so slow that I cannot play it: I get less than 10 fps. The lag is caused by the redundant lava tiles in the lava tilemap. tower_of_ghosts_slow.stl.zip

tobbi commented 4 years ago

How about we accumulate the pulsinglight objects into one big one?

I should clarify: Find adjacent tiles and make bigger pulsing light areas out of those.

HybridDog commented 4 years ago

How about we accumulate the pulsinglight objects into one big one?

It probably also happens with other game objects, not only pulsing lights. If the general case is fixed, SuperTux may be faster in many levels. I thought about grouping the game objects in different lists, but I do not know if the get_objects_by_type is the reason for the lag.

mstoeckl commented 1 week ago

I thought about grouping the game objects in different lists, but I do not know if the get_objects_by_type is the reason for the lag.

It is most likely one of the causes.

I've occasionally been profiling SuperTux using perf (specifically, perf record --call-graph dwarf supertux2 path/to/level.stl, and then perf report), and have found get_objects_by_type and get_object_count calls have been a major cause of lag in busy levels.

If dynamic_cast takes 10ns, and there are 2000 objects in total, then each GameObjectManager::get_objects_by_type call would take 0.2ms by itself; if the objects on screen call it a total of 20 times per game logic update, then get_objects_by_type alone would cost 4msec, which when combined with rendering time and other delays is enough to miss frames.