Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[help needed] this line of code is messing with my framerate (30 fps -> 2 fps)

Discussion in 'Entity Component System' started by Mr-Mechanical, Dec 16, 2018.

  1. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    I am using a ComponentSystem and I am trying to resolve the performance issue apparently caused from this line of code that is updating a component value:

    componentDataFromEntity[entity] = new SomeComponentData {Value = someValue};

    When this code is commented out my performance is reasonable, however, when the line of code is reenabled my framerate drops substantially. My guess is that creating a new SomeComponentData every assignment kills performance but I'm not sure. Thanks a lot, any help would be appreciated.
     
    Last edited: Dec 16, 2018
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,752
    We need more code. How often is this being called per frame.
     
  3. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    This code is being executed in a system which is updated at a fixed frequency of 1000hz. It's executing in an IJobParallelFor.

    I have a
    [NativeDisableContainerSafetyRestriction]
    public ComponentDataFromEntity<SomeComponent> componentDataFromEntity;


    and a

    [ReadOnly]
    public ComponentDataArray<EntityValue> entityValues;


    then in the Execute(int i) in the IJobParallelFor

    I have the following code:

    Code (CSharp):
    1. componentDataFromEntity[entityValues[i].Value] = new SomeComponentData {Value = someValue};

    The someValue is a variable of type float3 and is computed beforehand.
     
    Last edited: Dec 16, 2018
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,752
    How many iterations, because 1000hz seems really high.
     
  5. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    The systems are updated with UpdateAfter FixedUpdate and there is a good reason for the high frequency (however my project is a secret for now so I can't say much). This code is executed once per entity. That line of code is the only culprit for poor performance it seems.
     
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,752
    Yeah I'm asking how many entities are you working on.
     
  7. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    A few thousand
     
  8. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,752
    So that is millions of calls to componentDataFromEntity[entityValues.Value] per second.

    That's probably just not going to happen.
     
  9. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    Do you think it could be creating a new SomeComponentData each assignment that causes the performance hitch?

    I've replaced
    Code (CSharp):
    1. componentDataFromEntity[entityValues[i].Value] = new SomeComponentData {Value = someValue};
    with
    Code (CSharp):
    1. SomeComponentData someRandomComponentData = componentDataFromEntity[entityValues[i].Value];
    and I am back to 30fps : /

    But what ways can I avoid using "new"

    only way I can think of is using IJobProcessComponentData
     
    Last edited: Dec 17, 2018
  10. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,752
    No. New struct costs should be very cheap.

    Have you tried benching this in a build instead of editor?

    Editing a ref is much faster than setting component data from entity .
     
    Mr-Mechanical likes this.
  11. capyvara

    capyvara

    Joined:
    Mar 11, 2010
    Posts:
    80
    This last replace will probably be eliminated by the compiler if you don't use the someRandomComponentData in any place.

    This being said, the problem is not just on the new SomeComponentData call, but the fact the you're accessing the component by entity and there's no guarantee of linear memory access in this case. Can't you use IJobProcessComponentData ?

    Also, try in the player release build, editor runs code way slower due to a lot of checks.
     
    Mr-Mechanical likes this.
  12. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Don't set data with:
    componentDataFromEntity[entityValues.Value] = ...


    use instead:
    EntityCommandBuffer.SetComponent(index, entityValues.Value, myValue);

    I'm even not sure why this is working:
    componentDataFromEntity[entityValues.Value] = ....

    in the past it was readonly access....
     
    Mr-Mechanical likes this.
  13. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    No, you can do this directly, I use it in many cases in our game. GetBufferFromEntity\GetComponentDataFromEntity has argument for read or RW -
    GetBufferFromEntity\GetComponentDataFromEntity(bool isReadOnly)
    You just must be shure in safety, and if you shure, it most performant than ECB queue.
     
    Mr-Mechanical and Spy-Shifty like this.