Jondolf / avian

ECS-driven 2D and 3D physics engine for the Bevy game engine.
https://crates.io/crates/avian3d
Apache License 2.0
1.55k stars 120 forks source link

Optimize `wake_on_collision_ended` when large number of collisions are occurring #508

Closed datael closed 2 months ago

datael commented 2 months ago

Objective

Solution

I believe this is ok because the side-effects of that loop is to remove the Sleeping component and to reset TimeSleeping to zero, which is exactly the condition it now tests for. Therefore, if the entity is already in that state, there's no point in executing the relatively costly if statement here (as mentioned above).

Results

Large numbers of colliders (here, 2500) showed a near 1000x improvement in execution time of wake_on_collision_ended, going from multiple milliseconds to a few microseconds when none of the bodies are sleeping:

2500

Performance regressed for small numbers of colliders (here, 100), however this is regression at the microseconds level (3.5μs to 15.5μs median), so I posit that this is a worthy tradeoff: (removed; I had the traces backwards)


Changelog

datael commented 2 months ago

Correction: This is still an improvement for 100 colliders, though as mentioned in the original post it's in the region of microseconds so isn't particularly notable:

Screenshot 2024-09-07 at 19 01 34
datael commented 2 months ago

Assuming I'm looking at the correct section of the trace, gating the removal of Sleeping on the entity actually having it is also an improvement over previous, but this is even more negligible than the 100 collider case

Screenshot 2024-09-07 at 19 06 31
datael commented 2 months ago

As a sanity check and to rule out that it wasn't something particular in my scene, this is the move_marbles example in avian2d:

Screenshot 2024-09-07 at 20 03 45