Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by michael-bartnett · Jun 12, 2012 at 03:35 PM · coroutinesmemory-leakstartcoroutinec#-and-js

Do recursive coroutines leak memory?

I've got a function that needs to run roughly every half second, so naturally I'm looking at a coroutine.

I'm just curious, is this sufficient, or will this cause the stack frame associated with this coroutine to get bigger and bigger over time?

 void Start ()
 {
     StartCoroutine(LookForSquidward());
 }
 
 IEnumerator LookForSquidward()
 {
     yield return new WaitForSeconds(0.5f);
     if (IsThisPatrick()) {
         Debug.Log("Yes, this is Squidward.");
     } else {
         Debug.Log ("No, this is Patrick.");
     }
     StartCoroutine(LookForSquidward());
 }


I know the approach of using a while loop instead of a recursive StartCoroutine would unambiguously not grow the stack frame, but I'd like to know the specifics of how this approach works (or doesn't).

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Wolfram · Jun 13, 2012 at 01:56 AM 0
Share

Relatively unrelated to your question, ins$$anonymous$$d of constantly polling/querying whether it's Patrick or Squidward, it might be better, more elegant, and more to the point if the event that replaces Patrick with Squidward and vice versa would directly call a callback function such as NowItsSquidward() and NowItsPatrick() respectively. This could also be implemented via EventHandlers.

avatar image michael-bartnett · Jun 13, 2012 at 02:29 AM 0
Share

Well, yes, haha, that would be more efficient. This is a contrived example optimized for humor rather than an ideal implementation of Squid/Patrick detection.

1 Reply

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by Kryptos · Jun 12, 2012 at 03:53 PM

This way this will work because the coroutine is not stricly recursive: each coroutine overlaps the next one for one frame. To be recursive, and hence have possible issues, you would need to do that instead:

 // FAULTY CODE. DON'T DO THIS. 
 void Start ()
 {
     StartCoroutine(LookForSquidward());
 }
 
 IEnumerator LookForSquidward()
 {
     yield return new WaitForSeconds(0.5f);
     if (IsThisPatrick()) {
        Debug.Log("Yes, this is Squidward.");
     } else {
        Debug.Log ("No, this is Patrick.");
     }
     yield return StartCoroutine(LookForSquidward());
 }

But IMHO, using loops is a better approach. Still, your code works and doesn't raise any recursive issue.

Comment
Add comment · Show 13 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jun 12, 2012 at 04:00 PM 2
Share

It's generally not good to post negative examples ;) I've done so as well, but you should mark it as faulty code. Something like:

 // DON'T USE THIS
avatar image michael-bartnett · Jun 13, 2012 at 01:05 AM 0
Share

Thanks for answering, that makes sense, good to know that coroutines don't cause the stack to grow unnecessarily. Is there a specific reason why loops are preferred in general? It makes sense that algorithms that would read better recursively are implemented iteratively for game development (ie: recursive DFS of the hierarchy would be wasteful). But in this case it seems like the amount of memory allocated is about the same. Is this correct? If so, why are loops preferred over recursive coroutines in cases like this?

avatar image Wolfram · Jun 13, 2012 at 12:59 PM 1
Share

It's not just the allocation (although I realise your question is mainly concerned about memory usage), it's the complete setup and handling of a coroutine each time. Although I'm not sure how coroutines are exactly handled internally, it will involve stack access, additional function calls, probably managing the internal list of active coroutines, and so on.

Plus you'll also have to do the yield new WaitForSeconds anyway.

avatar image Max-Pixel · Mar 30, 2014 at 11:42 PM 2
Share

@Bunny83

Got it, that answers my question. Personally, I was pursuing this because I have a need for a repeated action that will happen at a different random interval each time, so the static interval of InvokeRepeating doesn't do the job. I hadn't thought of using a loop IN a coroutine. It seems, then, a standard template for repeating a function at a dynamic interval would be:

 public void Start() {
     StartCoroutine("Loop");
 }
 
 private void Loop() {
     while (true) {
         // Do something here
         yield return new WaitForSeconds(someFloatThatGetsChangedNowAndThen);
         // Alternatively, or in addition, do something here
     }
 }
avatar image michael-bartnett · Mar 30, 2014 at 11:50 PM 1
Share

@$$anonymous$$ax-Pixel

That's the right idea. The clearest and most efficient approach in these cases is a loop within the coroutine. I was asking about using recursive coroutines out of curiosity and because of a weird case that ended up being clearer with a loop anyway.

$$anonymous$$ake sure your Loop function returns an IEnumerator, and if you don't expect this script to get destroyed remember to give yourself an exit condition (whether in the while statement or via a break somewhere in the loop body) so you can end your coroutine.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

9 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Coroutines and states 1 Answer

Brain exploding ... Problem with an internal Coroutine manager 3 Answers

Can't Stop couroutines 1 Answer

Dynamically updating a Coroutine's parameters every frame 1 Answer

Why doesnt my coroutine ever end? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges