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

Something seems wrong? Acessing ComponentData values is very expensive.

Discussion in 'Entity Component System' started by auhfel, Mar 21, 2018.

  1. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    In a ComponentSystem's OnUpdate, accessing one of the variables from a ComponentDataArray is really expensive.

    With this rather simple system I was playing with, it was taking like 60ms or so just to access the variables, and I don't do anything but access the values in the OnUpdate. This is running on 50k entities.

    public class MyRendererSystem : ComponentSystem
    {
    public struct Data
    {
    [ReadOnly] public int Length;
    // [ReadOnly] public SharedComponentDataArray<MyRenderer> MyRenderers;
    [ReadOnly] public ComponentDataArray<MyPosition> Positions;
    [ReadOnly] public ComponentDataArray<Rotation> Rotations;
    }

    [Inject] private Data m_data;

    protected override void OnUpdate()
    {
    for(int i= 0; i < m_data.Length; i++)
    {
    float3 position = m_data.Positions[i].Value;
    float3 rotation = m_data.Rotations[i].Value;
    }
    }
    }


    Am I doing something wrong? Or is there a bug?

    On JobComponentSystems it seems fine, but on regular ComponentSystems it's messed up.
     
    Last edited: Mar 21, 2018
  2. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    I tried it again and it seems like it only took absurdly long while deep profiling in the editor. With normal profiling, the above takes about 5ms to process. That still seems like a very long time to process 50k entities without actually doing anything, though. I feel like it should easily be sub-1 ms.
     
  3. Zentropy

    Zentropy

    Joined:
    Sep 30, 2016
    Posts:
    3
    Just in case anyone else is wondering - this happens due to
    #if ENABLE_UNITY_COLLECTIONS_CHECKS
    GetValueCheck(index);
    #endif


    inside of the element accessor in ComponentDataArray. I tried undefining said define and another piece of code elsewhere blew up, so I'm guessing this is currently forced-on but will later be an option. I straight up deleted that chunk and it dropped execution of auhfel's code from 5ms to 0.8ms. You probably do not want to do this right now, but now everybody knows. Cheers!
     
    auhfel likes this.
  4. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Before you go modifying the ECS code, did you try profiling it in a player, rather than the Editor?
     
  5. TheRealBait

    TheRealBait

    Joined:
    Mar 22, 2018
    Posts:
    1
    haha classic unity™ employee response, so instead of giving some insight regarding the absurd 60ms frame time op's code was taking, or acknowledging zentrophy's findings about the cause, this is what we get, a snarky response. maybe next time before you reply, you can ask yourself "what would joachim say"
     
  6. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    I'm not really sure why I would have tested it in a player. It's not for a release or production, I don't have a game built for ECS or anything yet. Just simply testing out systems in ECS to experiment. I wanted to try my hand at making my own render system using Graphics.DrawMeshInstanced because I figure it'd be good practice to learn ECS. Anyways, with the Unite Austin tech demo showing 50k entities I figure I should be able to do something comparable, yet it was incredibly slow in the editor and I was just wondering why, after doing some profiling.

    Anyways, I think the answer here is just "it's slow because we're doing some error checking". It's safe to assume that this is for editor only stuff and probably will be disable-able like the Job system stuff can be in the Job menu. Never intended to fix it myself I was just wondering what was up. Now that I'm aware I can test more comfortably and not worry about it.
     
  7. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,114
    From what I understand, editor has safety system for error checking so it will slow down. It's always best practice to profile real player build instead of editor to see the real performance. That is why superpig asking that question.
     
    MadeFromPolygons, Krajca and superpig like this.
  8. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    I can see where you are going with this, but the question doesn't really contribute to the original question. If I tried debugging the player instead, and the problem disappeared, I'd still be wondering why the performance was so bad in the editor, as that is where most of if not all of my ECS testing will occur. It kinda just feels like I put some good faith in trying to debug the problem myself, even coming back the next day after testing more, and then we find out why it's slow, and then afterwards get a low-effort response that kind of ignores all the fact-finding and answer finding that we already did and just feels like a jab. We were not trying to fix ECS or anything -- just wanted to know what was up with something that seemed to be working incorrectly.
     
  9. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    I'm sorry it felt like a jab, but I meant the question sincerely. I wanted confirmation that the performance issues went away in the player before talking about the safety checks, because if they hadn't then it would have been much more interesting.
     
    MadeFromPolygons, Krajca and auhfel like this.
  10. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,114
    Btw @superpig any plan to make the profiler result to be as near to real player build as possible? Maybe have a option to remove safety check at profiler or option to enable pseudo profiling that is near to real player build result.
     
  11. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    I don't want to speak for the ECS team on this as I don't know their exact plans, but I agree that we need to solve the problem. It's already possible to disable some of the safety checks via the Jobs menu ("Enable Burst Safety Checks" and "JobsDebugger" - though the risk is that you'll crash Unity). Possibly you'll see more options show up there in the future.
     
  12. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    It's no problem. I suppose I'm just haunted by the times I've called the internet company to get something fixed, go through some troubleshooting, only to have the call dropped and have to go through it all again. Not the same thing, but a similar feeling.

    I was able to build the project to my phone yesterday, but for some reason the entities package is now complaining that some stuff doesn't exist whenever I try to build now. It's late tonight but I'll try again tomorrow to see if I can get it to build and see if the profiler shows the same issue in a build.
     
  13. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Hi auhfel,

    The code looks fine. There are likely a few explanations for performance in editor you are seeing.

    1. ComponentSystem automatically completes any previous jobs that may be reading / writing to the components of the same type before it runs. So if there are some long running jobs just scheduled just before against same component types, then you will get a sync point at this point.
    (JobComponentSystem does not create such syncpoints, it simply schedules more jobs with the correct set of dependencies)

    2. In The editor in mono the race condition safety system & "did someone destroy this thing" checks always run. It can't be stripped out or disabled at the moment in the editor. As a result when running with il2cpp / mono in the player you will see some very signficiant speedups I would expect on the order of 10x for the code you posted.

    As a result the best approach is to simply write all of your code in C# jobs, using burst, where you can get the absolute best in performance. A really useful thing in burst is that we can turn off the safety checks in the editor for example when profiling. (Jobs -> Enable Safety Checks) Also "Jobs -> Enable Job Debugger" is a very useful menu item to avoid main thread scheduling safety checks.

    I'd love to what performance using the code you have with ComponentSystem is in IL2CPP in standalone player and also how its working for you when you move it to burst?
     
    Last edited: Mar 25, 2018
    FROS7 and Zentropy like this.
  14. Zentropy

    Zentropy

    Joined:
    Sep 30, 2016
    Posts:
    3
    Thanks for responding and confirming I was right and it was the safety checks Joachim! Really enjoying being able to dig into the code for this crazy awesome ECS
     
  15. auhfel

    auhfel

    Joined:
    Jul 5, 2015
    Posts:
    92
    I've written in Job/Burst a very simple move forward system, and the performance is quite exceptional. At 250k entities the move forward system(burst) is something like .04ms on my pc. It's almost nothing, the only thing that is actually costing any performance is the MeshInstanceRenderer system.

    On a mobile build (Xiaomi Redmi Note 4x) with IL2CPP, my simplistic MoveForward ComponentSystem (position + heading*speed*time) is taking ~ 65ms for 250k entities, taken from the profiler. This sounds fairly good, given that it's mobile (not even top tier mobile) and not using any threading at all (despite it's deca core processor!). Great job so far.

    I do plan on writing everything I can in Jobs/Burst, because the performance is crazy good. What stemmed this particular thread though was needing to use the main thread because of Render calls. I for sure will write what I can in jobs!

    EDIT: I also tried with IL2CPP + Jobs, no burst obviously. The movement system wasn't registering anything in the profiler, was showing 0ms. Not sure if I was looking at the wrong item or anything, but it seems like it took practically nothing with the multithreading from jobs.
     
    Last edited: Mar 27, 2018
  16. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,967
    unwarranted and uncalled for, also unprofessional. Please read all posts next time to get an understanding before posting.
     
    NotTesla and RaL like this.
  17. Tudor_n

    Tudor_n

    Joined:
    Dec 10, 2009
    Posts:
    359
    Necroing but could be useful to know. In my tests, the frame times displayed in the enity debugger, are bugged. If you turn off the instanced mesh drawing or remove the comp, you'll see that frametime magically moving to another system. Most likely yours.
     
    Last edited: Apr 7, 2018
  18. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    EntityDebugger currently only shows main thread time. Thus sync points will show up heavily, otherwise for JobComponentSystem it will only show the cost to schedule the jobs...

    We are planning on showing both total time across all threads + main thread cost.
     
    FROS7 likes this.
  19. Tudor_n

    Tudor_n

    Joined:
    Dec 10, 2009
    Posts:
    359
    Was sure it was just the main thread, but wasn't sure what from. Having execution times across threads would be a very welcome addition as currently it's very hard to reason how your code will scale with num. of cores, big-little setups, etc. That or some straightforward way to only keep things on the main thread so you can, at least, gauge execution time for individual systems.