Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  OBI Performance degradation over time
#1
Hi,

I have a collection of issues relating to performance degradation over time in the scene when using Obi Cloth on relatively complex 2-manifold meshes. I am creating a game where you inflate objects (such as life rafts, balls, Santas, snowmen, etc). The inflation mechanic works pretty well. However, on some meshes, there are odd performance issues. Apologies, this is going to be a couple of odd observations that may or may not be related.

I have noticed that as the scene is running, increasing calls are being made to ObiFixedUpdator.FixedUpdate/Substep. It increases from 5 (which is what I expect) and then after a minute can increase to 20 or 25 which is where the issues start. Even if there is no action in the game, this number starts increasing.

Some odd things I have noticed...

Once the issue starts, it persists even after I reload the same scene (like in a replay game). In fact, it can be even worse when I reload the scene. However, if I reload the scene quickly a few times, it seems to reset the calls back to a low number, and it behaves normally. 

Even more oddly, if I destroy the object that has the obi solver and the obi actor, then wait a few seconds, reloading the scene will result in disastrous performance. Performance is good when I have destroyed the object before I reload the scene, but then the number of calls immediately goes to 30+ on the next scene when the OBI object returns. It's almost like there is a leak somewhere, and reloading the scene doesn't fix it (though reloading it frequently in quick succession does). Note, I destroy the object when the inflatable object has "exploded" due to over-inflation (my own mechanic). Is it wrong to destroy the OBI Solver and Actor?

The mesh with the problem has 2362 triangles and is the only OBI actor in the scene. I also have an OBI Collider, an OBI rigid body, and an Obi Particle attachment on it.

I have tried both Oni and Burst and the problem occurs with both, though I think Oni is a little better. With Burst, I have safety checks switched off of course.

Thanks in advance.

michael.
Reply
#2
(09-01-2024, 09:55 AM)michendo Wrote: Hi,

I have a collection of issues relating to performance degradation over time in the scene when using Obi Cloth on relatively complex 2-manifold meshes. I am creating a game where you inflate objects (such as life rafts, balls, Santas, snowmen, etc). The inflation mechanic works pretty well. However, on some meshes, there are odd performance issues. Apologies, this is going to be a couple of odd observations that may or may not be related.

I have noticed that as the scene is running, increasing calls are being made to ObiFixedUpdator.FixedUpdate/Substep. It increases from 5 (which is what I expect) and then after a minute can increase to 20 or 25 which is where the issues start. Even if there is no action in the game, this number starts increasing.

Some odd things I have noticed...

Once the issue starts, it persists even after I reload the same scene (like in a replay game). In fact, it can be even worse when I reload the scene. However, if I reload the scene quickly a few times, it seems to reset the calls back to a low number, and it behaves normally. 

Even more oddly, if I destroy the object that has the obi solver and the obi actor, then wait a few seconds, reloading the scene will result in disastrous performance. Performance is good when I have destroyed the object before I reload the scene, but then the number of calls immediately goes to 30+ on the next scene when the OBI object returns. It's almost like there is a leak somewhere, and reloading the scene doesn't fix it (though reloading it frequently in quick succession does). Note, I destroy the object when the inflatable object has "exploded" due to over-inflation (my own mechanic). Is it wrong to destroy the OBI Solver and Actor?

The mesh with the problem has 2362 triangles and is the only OBI actor in the scene. I also have an OBI Collider, an OBI rigid body, and an Obi Particle attachment on it.

I have tried both Oni and Burst and the problem occurs with both, though I think Oni is a little better. With Burst, I have safety checks switched off of course.

Thanks in advance.

michael.

Hi Michael,

What you describe is just how fixed time stepping works in games, nothing odd about it.

Fixed timestepping is a way of updating physics using fixed time intervals. Since games update at a variable frequency (sometimes more FPS, sometimes less), a way of making sure physics stay consistent is by accumulating the amount of time taken by each frame and then calling physics -FixedUpdate(), in Unity's case- as many times as needed to keep up with rendering.

So let's say we are updating physics at 50 hz (one update every 0.02 seconds), and 0.05 seconds have passed since the last frame. We have to update physics 0.05/0.02 = 2 times this frame. There's 0.01 seconds remaining that we will accumulate, so no more physics steps until there's at least 0.02 seconds worth of time accumulated.

Problem is, what happens when a single frame takes a lot of time to process - for whatever reason?. In these cases, a lot of time will be accumulated leading to a lot of physics updates necessary. Updating physics a lot of times is slow though, so this causes the next frame to also take a lot of time, leading to even more physics updates, which in turn make things even slower and leads to even more physics updates, etc. This is a downwards performance spiral situation, generally known as death spiraling, which is what you're experiencing. Once the spiral is in motion, it can be very hard to get the game out of it and the only solution is often to significantly reduce workload for a few frames giving the engine time to recover.

Ideally, your game should have enough performance headroom and run smoothly enough that processing a frame never takes enough time to trigger the spiral. While this isn't easy as it may mean optimizing everything across the board, a simple solution to alleviate this situation is to reduce Unity's "max allowed timestep" setting, which will tell Unity to stop updating physics if a frame takes too much time to process. If this is your first time hitting a timestepping related issue, I'd suggest reading about it online. There's hundreds of very good resources of this topic, some focusing on Unity in particular - since this is common to all game engines, not just Unity or Obi. See:

https://gamedevbeginner.com/how-to-use-f...-in-unity/
http://blog.lidia-martinez.com/fixedupda...step-unity
https://forum.unity.com/threads/what-is-...ep.330116/
https://gafferongames.com/post/fix_your_timestep/

kind regards,
Reply
#3
(09-01-2024, 10:28 AM)josemendez Wrote: Hi Michael,

What you describe is just how fixed time stepping works in games, nothing odd about it.

Fixed timestepping is a way of updating physics using fixed time intervals. Since games update at a variable frequency (sometimes more FPS, sometimes less), a way of making sure physics stay consistent is by accumulating the amount of time taken by each frame and then calling physics -FixedUpdate(), in Unity's case- as many times as needed to keep up with rendering.

So let's say we are updating physics at 50 hz (one update every 0.02 seconds), and 0.05 seconds have passed since the last frame. We have to update physics 0.05/0.02 = 2 times this frame. There's 0.01 seconds remaining that we will accumulate, so no more physics steps until there's at least 0.02 seconds worth of time accumulated.

Problem is, what happens when a single frame takes a lot of time to process - for whatever reason?. In these cases, a lot of time will be accumulated leading to a lot of physics updates necessary. Updating physics a lot of times is slow though, so this causes the next frame to also take a lot of time, leading to even more physics updates, which in turn make things even slower and leads to even more physics updates, etc. This is a downwards performance spiral situation, generally known as death spiraling, which is what you're experiencing. Once the spiral is in motion, it can be very hard to get the game out of it and the only solution is often to significantly reduce workload for a few frames giving the engine time to recover.

Ideally, your game should have enough performance headroom and run smoothly enough that processing a frame never takes enough time to trigger the spiral. While this isn't easy as it may mean optimizing everything across the board, a simple solution to alleviate this situation is to reduce Unity's "max allowed timestep" setting, which will tell Unity to stop updating physics if a frame takes too much time to process. If this is your first time hitting a timestepping related issue, I'd suggest reading about it online. There's hundreds of very good resources of this topic, some focusing on Unity in particular - since this is common to all game engines, not just Unity or Obi. See:

https://gamedevbeginner.com/how-to-use-f...-in-unity/
http://blog.lidia-martinez.com/fixedupda...step-unity
https://forum.unity.com/threads/what-is-...ep.330116/
https://gafferongames.com/post/fix_your_timestep/

kind regards,

Thanks josemndez. 

That is useful information. But there is something you had not addressed:  the massive effect that destroying the OBI Solvr and Actor is having on performance, the next time I load the scene, leading me to think I should not be destroying the solver, perhaps it is persisting in memory, even after the scene is reloaded. Is that the case? 

Regards,

Michael.
Reply
#4
(10-01-2024, 09:45 AM)michendo Wrote: But there is something you had not addressed:  the massive effect that destroying the OBI Solvr and Actor is having on performance, the next time I load the scene, leading me to think I should not be destroying the solver, perhaps it is persisting in memory, even after the scene is reloaded. Is that the case? 

Hi,

Destroying a solver may release a large amount of memory, which is bound to have an impact on performance. Conversely, creating a solver may allocate quite some memory, depending on how many actors are being managed by that solver - and how complex they are. Adding new actors to a solver is also relatively heavy, as it may trigger an internal resizing of the solver resources (basically, lists of particles & constraints) and it also requires copying a considerable amount of data. See:
http://obi.virtualmethodstudio.com/manua...cture.html

(10-01-2024, 09:45 AM)michendo Wrote: but then the number of calls immediately goes to 30+ on the next scene when the OBI object returns

This of course can trigger multiple FixedUpdate calls / death spiralling, like any other performance intensive action. Creating a new solver and adding a new large actor to it requires allocating quite some memory, as well as copying a lot of blueprint data. Like usual in Unity, you must avoid creating/destroying large objects at runtime and use pooling instead.
Reply