Entity.Simulate really expensive

Options
Currently, I have ~50 entities in the scene with an Authoritative server setup. All of my logic for these entities is in OnSimulateOwner() so technically, there shouldn't be too much processing on any clients that are connected.

However, I have noticed a significant drop of fps as the number of entities goes beyond 20 (on clients). I did a deep profile check and turns out that 50 - 60% is in BoltPoll.FixedUpdate(). I'm attaching a screenshot of the Profiler info.

Also, all these entities have Mecanim synced over Bolt as well.

Are there any specific bolt settings to avoid this? Any help on this would be greatly appreciated.


Comments

  • stanchion
    stanchion mod
    edited December 2015
    Options
    What is done in your OnSimulateOwner() function? You probably need to do freezing on the server, and scoping to limit the number of entities being synced with clients. This may also be due in part to the mecanim
  • Tobias
    Options
    There are quite a lot of OnSimulate*() calls. The "Self" time for both is only a small(er) part of the time spent here. A good chunk of the time is spent inside the implementations.

    I think scoping is a good idea. Also have a look at what's happening even further down the call tree.
  • DirtyHippy
    Options
    This is not really a question of scoping. This is due to the design of how bolt handles state properties. This system likely needs to be redesigned a bit, which would be a lot of work.

    This is all from memory, but fundamentally each time ticks are evaluated, every state property in every entity is evaluated. Each property exposes a getter which says "I need a simulate before" or "I need a simulate after". Bolt loops over each of these properties and asks if it needs a simulate (depending on what simulate step it is on).

    OnSimulateBefore - typically interpolated properties request this simulation step
    OnSimulateAfter - Mecanim state properties request this step

    I typically see humongous times allocated to OnSimulateAfter, because I have many state properties that are associated with Mecanim. Bolt sets the state of every mecanim state property in the animator regardless if it has changed every time this is evaluated. This is likely because A) it is easy and B) I am guessing properties with dampening require it. The problem is that frame coherence for mecanim state properties (and likely all state properties) is almost 100% - that is, state properties change extremely rarely. When you are running an animator, how often do you change the state of a property in the animator? A few times a second? But Bolt syncs every property every simulate tick. The cost here will be the iteration cost for tons of properties (and likely cache misses since the properties are likely heap allocated), as well as the interop cost of calling into Mecanim for every Mecanim property every simulate tick. There is also an unknown cost of Unity's implementation. That is, who knows what Unity does under the hood - does it check if the values are the same and just early out? Or does it actually set the value and incur more cost?

    I think there is likely a better way to approach this, based on some type of dirty bit approach, where only states that have been dirtied since the last simluate tick are applied to the animator (with special consideration given to the initial sync of a newly scoped entity). If this was implemented there would be almost zero cost for OnSimulateAfter, since no properties would be iterated at all in most simulate ticks (and in the cases where they were, only a few properties would be evaluated). I filed a Github request on this already. I am pretty sure I could implement my own custom Mecanim syncing manually, through state properties that would dramatically reduce the overhead of the syncing.

    That being said, I'm not sure why OnSimulateBefore is so high here in the OP - note that there are a lot of costs in the debug mode of Bolt relating to assertions and other checks, and in addition deep profiling percolated some false positives due to the way sampling works. Unfortunately, I cannot deep profile my stuff anymore - it just crashes if I try. However, this number is so high in the OP that I think it warrants more investigation as well.