Search Unity

IJobComponentSystem execution order or jobs dependency issue at high CPU loads

Discussion in 'Entity Component System' started by DrSpritz, Jun 19, 2018.

  1. DrSpritz

    DrSpritz

    Joined:
    Oct 6, 2013
    Posts:
    29
    Hi,

    Today i ran into case, when IJobComponentSystem execution order looks broken. You can see that in sample project, that reproduce this case here https://github.com/drSpritz/unity-job-system-execution-order-issue

    Logic of working a systems is very simple. The project have two systems, first one "SpeedSystem" - copy value (100f) from "Speed" component to "MoveSpeed" component. Second system "ModifySpeedSystem" just multiply "MoveSpeed" component value (100f) by self value (0f). The order of execution of these systems is strictly specified - "SpeedSystem" calls before "MoveForwardSystem" and "ModifySpeedSystem" calls before "MoveForwardSystem" but after "SpeedSystem".

    If you open SampleScene from the project, you can find two game objects, called "IgnoreSystemsOrder_Spawner" and "SuccessSystemsOrder_Spawner". Difference between theese objects is just an instances count, that script will be spawn.

    First case:
    - Enable "SuccessSystemsOrder_Spawner" and hit play. As result you will be see cloud of 1000 cubes. Theese cubes won't move, because "ModifySpeedSystem" multiply 100f by 0f and get 0f as result.

    Second case:
    - Enable "IgnoreSystemsOrder_Spawner" and hit play. As result you will be see cloud of 100000 cubes. Theese cubes will be move, that marks the "ModifySpeedSystem" doesn't work correct.

    As i understand, when CPU get high loads the systems execution order or Jobs dependency for some reason not respects.

    Unity 2018.2.b8
    "com.unity.entities": "0.0.12-preview.6"


    What do you think about it?
     
  2. DrSpritz

    DrSpritz

    Joined:
    Oct 6, 2013
    Posts:
    29
    Up!

    I changed all systems from IJobComponentSystem to ComponentSystem. Now all systems code executing on main thread and all working fine! You can checkout that in mainThreadSystems brunch.

    Guys, it looks like IJobComponentSystem realy have an issue or i missunderstood something.

    Please, somebody check it. Will you have same results? This case caught my mind and don't want to release me))
     
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    I found your mistake but maybe part of it is a bug as well. First of all your assumption that the less cube does not move at all is incorrect, in my machine if I stare at them long enough sometimes some of them moves. Indicating that this problem comes from sometimes MoveForwardSystem getting the 100 speed and sometimes 0 speed.

    When you look in Timeline, it seems that MoveForwardRotation and therefore TransformSystem (they have deps against each other) decided to run whenever it wants in between your Speed and OverrideSpeed. When you have more cubes it is just that these 2 happen to be able to run before any OverrideSpeed so they all get 100 speed. (But look closely some of them will not move in a frame.)

    Screenshot 2018-06-21 19.13.30.png
    But why it does not wait when you put [UpdateBefore(typeof(MoveForwardSystem))] ? Your mistake comes from here
    public void Execute([ReadOnly] ref MoveSpeed moveSpeed,[ReadOnly] ref ModifySpeed overrideSpeed)
    (and the other one) which you are modifying moveSpeed but you mark it as [ReadOnly]. I said it is an ECS bug as well because it should have warn you that you cannot write into a [ReadOnly]. Anyways turns out you can actually write into it but the automatic dependency system (inputDeps) look at [ReadOnly] and it thought that it is fine to run a job concurrently without waiting despite the [UpdateBefore] you put on. Therefore you get this strange behavior. Removing the first [ReadOnly] should solve this and I suggest you also report your project as a bug about [ReadOnly] should throw thing.
     
  4. DrSpritz

    DrSpritz

    Joined:
    Oct 6, 2013
    Posts:
    29
    Yeah, i was believe that if i not replace full component struct (same as it's done with [Injected] ComponentDataArray) it is not are a write operation (at this momen i'm understand how it stupid sounds). Thank you very much, it works!

    Yes, I will send a bug report. In this case a warn message will be very useful, because this mistake cost me many hours of wasted time.