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

Slow coroutines. Where is the slow down coming from?

Discussion in 'Scripting' started by Xbelt, Apr 17, 2014.

  1. Xbelt

    Xbelt

    Joined:
    Nov 27, 2013
    Posts:
    8
    Hello,

    In my current project I am using coroutines for some work. Now I was wondering why my performance was not good enough, so I tried measuring the time it takes for a single call as follows:

    Code (csharp):
    1. var sw = new Stopwatch();
    2.                 sw.Start();
    3.                 yield return StartCoroutine(VisitDraw(child));
    4.                 sw.Stop();
    5.                 Debug.Log("Draw time: " + sw.ElapsedMilliseconds);
    where VisitDraw is the coroutine called. Now I get times ranging from 18ms to 32 ms which is way too high since i can only allow something around 1ms for such a call.
    Now if I measure the time inside the VisitDraw method from the start until the yield break; call, I get constant timing of 0ms which is fine. Now my question is where do I loose the 30ms?

    Thanks for your time. If you need more code examples feel free to ask.
    Kind regards

    Lukas Häfliger
     
  2. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    when you yield, you know at least a frame will go by.

    If you have a FPS arround 60, each frame will be 1s / 60 = 0,0166s = ~17ms

    The time you measure isn't the time it really takes to compute the call, it's just the time it takes to get to that point in your code with the coroutine system...
     
  3. Xbelt

    Xbelt

    Joined:
    Nov 27, 2013
    Posts:
    8
    Is there a way to speed this up?

    And why does yield take up one frame? It is not called from within an update method or something like that.
     
  4. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    that's the use of yield, it allows you to scatter execution over multiple frames to avoid blocking your game for time consumming operations.

    What is the use of that method you call ? And why does it concerns you how long it takes to get to the end of it ? (for example, if you're worried because you have to call it many time, then don't [worry], just do it and let unity deal with it, or consider looping it while checking for time of frame, there are tons of solutions, it really depends on what you want to do)

    And maybe you don't even need coroutines or if your case is specific, you might need threads...
     
  5. Xbelt

    Xbelt

    Joined:
    Nov 27, 2013
    Posts:
    8
    Well the problem I am facing is that basically I need to draw some lines after each other. Depending on the value of a slider there should be a delay between all line drawings. (Ranging from lets say 0s to 1s)

    I am using coroutines because I cannot use threads because I need to populate the gameObject object and need to perform some drawing calls.
    In a first step I had a solution but it was very ugly. I started the aforementioned method in a thread and generated some basic commands which I put into a thread safe queue. Then in another script I just dequeued elements when a certain time has passed and performed the drawing command. But as mentioned this was very ugly and I am hoping to find a better solution.

    Is there a possibility to return from a coroutine without yield? In that case I could return from the method when the drawing delay is small enough
     
  6. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    Hmm firstable, you don't have to yield when you start a coroutine, StartCoroutine() is asynchronous so you can continue with other business after calling it if you remove the yielding.

    Secondly, you could draw your line from within the Update() without coroutine, just by checking time no?

    Code (csharp):
    1.  
    2. public class       LineDrawer : MonoBehaviour
    3. {
    4.     public float   _delay = 0.5f; //Delay between line drawing
    5.  
    6.     private float  _nextDraw = 0;
    7.  
    8.     void           Update()
    9.     {
    10.          while (this._nextDraw < Time.time) //don't put a null value in the delay or you'll have an infinite loop on your hands ;)
    11.          {
    12.              VisitDraw(child);
    13.              this._nextDraw = this._nextDraw + this._delay;
    14.          }
    15.     }
    16. }
    17.  
     
    Last edited: Apr 17, 2014
  7. Xbelt

    Xbelt

    Joined:
    Nov 27, 2013
    Posts:
    8
    Perhaps I need to improve the description of my problem. The input I have is the AST (abstract syntax tree) of a language. Now depending on the nodes of the AST I need to perform certain actions like drawing and other commands. As mentioned, most of these commands need to have an adjusteable delay between each other. So the reason I used coroutines was that I could just walk over the tree and pause the walking sometimes when needed. But I see that there is no way to realize this with coroutines so I will probably go back to my first implementation which was very ugly...
     
  8. Deleted User

    Deleted User

    Guest

    I dont get it why you yield return on StartCoroutine(). Do you need to do that? Because that should be the reason for your high time values
     
  9. Xbelt

    Xbelt

    Joined:
    Nov 27, 2013
    Posts:
    8
    Yeah it was the nice looking version. So nevermind and thank you so much for your time. I really appreciate it!