I’m guessing you’re overloading the garbage collector by creating and deleting 3000 objects every second. I’m not sure how the transitions would be collected when they finish.
Thank you davemikesell for your input. It’s an interesting theory. I did some testing and found the following:
-
One millisecond is faster than the framerate so the code is generating and removing objects at the framerate so there is 90 objects generated each second (default framerate = 30 and I have three 1 millisecond timers). Please correct if my numbers are off.
-
The crash happens even if I launch just one timer and therefore generate and remove only 30 objects every second, it just takes a minute longer to crash.
-
On my machine the simulator crashes after 1.5min. If I don’t rotate the box (remove line 11) the simulator doesn’t crash even if I’m still generating and removing 90 objects every second. I let it run for 6 minutes without problems. What is going on!?
Yeah, good point about the frame rate.
I added a print of memory in CreateBubbles…it ramps up fast when things go south.
print(collectgarbage(“count”)/1024)
Thanks davemikesell for trying it out! I really appreciate it. I did some more testing and made the following observations:
- If I add some manual garbage collection(see below) it runs 2-3 times longer before crashing. So it does help, but doesn’t remove the issue. I notice that memory usage slowly raises all the time.
[lua]
local function GarbageCollection()
timer.performWithDelay(1, function() collectgarbage(“collect”) end)
end
timer.performWithDelay(5000,GarbageCollection,0)
[/lua]
- Still the simplest workaround is to stop the box rotation(remove line 11). This way it can run forever(tested for 10 mins) without any increase in memory or cpu usage. Why? It’s just one box that is nothing compared to hundreds of other objects. Is there a bug?
I would really appreciate if Corona Engineers would shed some light on this. Please help, I’m working on particle heavy app and this issue is keeping me from releasing it.
If you want an example of infinite particles you can take a look at this: https://dl.dropboxusercontent.com/u/10254959/StarField.zip
The routine can be modified for bubbles, snow, etc.
Commenting out FloatLeft(bubble) fixes the issue on my rig. I think your problem are the hundreds and hundreds of transitions making the bubbles float back and forth.
I would create say 3-4 display groups, put each bubble in a random group, and then float the display groups back and forth.
Alternatively, I would consider using sprites to do the FloatLeft animation, and only using transitions for the FloatUp part.
Thanks guys for taking part in this!
horacebury: Thank you for the awesome demo!
memo.development: Yes, that works. Also commenting out line 11 RotateBox(box) solves the issue. Could you try that? Why does it help since it’s just a one box? Thank you for the clever workaround solutions. In my app I have similar system with much less particles(just one 50 millisec timer generating particles which are always removed after 1.5sec. So I’m generating and removing just 20 particles/second. Is that too much? I have some other light stuff going on at the same time, but nothing too intensive.
I tested this with older build(2013.1137) and there are no problems. I let it run for 10min without any issues. Older build also uses 10-20% less CPU. I’m guessing there is some issue with the G2 graphics engine.
Anyone who tests this, please try to comment out line 11.
This is really weird. I’ve played with the code for a while and the crash doesn’t really make sense. Especially if, as you’ve noted, you removed the call to RotateBox() it runs forever. The fact that two (sequential) transition calls makes a difference is odd.
There are other ways to do “infinite” objects, such as just moving them back down to the bottom when they reach the top (instead of deleting them). In that case you’d only create a finite amount, so you wouldn’t need those eternal timers.
But that still doesn’t solve the mystery as to why the code shown is having problems. I would expect Corona to handle more objects than that without keeling over.
Jay
Don’t know - I commented out everything *except* the box code, and changed them to fire every 100 ms. Small leak over time, but nothing that should crash your program in a minute and a half. The fact that you can run this in older versions points to a Corona bug, I’m guessing in the transition code.
You have a very small code snippet that reliably illustrates the error. I’d open up a bug report with Corona Labs.
BTW, if you make heavy use of particles, you really need to check this out.
http://www.x-pressive.com/ParticleCandy_Corona/features.html
It’s your mixed use of “_object.transition” between FloatUp()/FloatLeft() that’s leaky. Would seem the FloatUp() transition isn’t getting cleared.
edit: good puzzle, here’s more. above is the fast-recurring easy-to-spot leak, but it’s trivial in the long run: the box rotate is the actually BIG problem, you just have to wait for it’s recursion to mount up. for example, comment out the print() in CreateBubbles() so that you can more clearly read this (apologies that i can’t get forum code formatting to work):
local function RotateBox(_object)
local function RotateBack()
collectgarbage(“collect”)
local mem = collectgarbage(“count”)
print("RotateBox at: " … system.getTimer() … " MEM: " … mem)
transition.to(_object,{delta=true, time=3000, rotation=30, onComplete=RotateBox})
end
collectgarbage(“collect”)
local mem = collectgarbage(“count”)
print("RotateBox at: " … system.getTimer() … " MEM: " … mem)
transition.to(_object,{delta=true, time=3000, rotation=-30, onComplete=RotateBack})
end
Thanks J.A. Whye and davemikesell for confirming the problem!
davebollinger: What do you mean FloatUp() transition isn’t getting cleared? It is not saved anywhere and it always runs completely. What’s there to clear?
Why the BoxRotate is a problem? I can’t see it leaking. Could you explain in detail what you mean? I made it rotate really fast and tested it for 3 minutes and memory usage stayed perfectly stable.
And just for the fun of it, if you break out the two functions (RotateBox and RotateBack) so they’re both peers of each other, rather than one being a child function, you get exactly the same thing happening.
I don’t see a leak between the FloatUp/FloatLeft – the up transition shouldn’t need to be cleared since the RemoveMe isn’t called until that transition is done. And inside FloatLeft/Right the transition handle is being saved so *that* can be cleared inside the RemoveMe function.
On the other hand, I just tried saving the handle to the up transition in _object.upTrans and then canceling it inside RemoveMe and … oh, never mind, just went back and checked and it was dead again. Drat.
Jay
polygonblog, it’s not the RotateBox itself, because you can just do that chunk of the code and memory stays solid like a rock. It’s when you do that along with the ball stuff. But why, I don’t know. I wish it wasn’t after 5AM here in Alaska, I’d like to poke at this more but my wife is going to yell at me as is when I “sleep in” until noon. :)
Maybe when I get up someone will have posted the answer. I hope it’s really hard to figure out so I don’t feel like a dope.
Jay
Thanks Jay! Have a good night!
davemikesell: Thanks for the suggestion. I’m aware of the Particle Candy. It looks really powerful, but I enjoy creating particle effects myself…as long as they don’t crash
I opened a bug case (30859).
you seem to need both “pieces” to get the full error, doesn’t seem to fully reproduce with either piece in isolation. but it’s the box rotation recursion that’ll eventually crash from its explosive growth.
somewhere between your 1ms timer potentially “flooding” some internal mechanism (despite the fact it can only come up for breath and actually execute it once per frame) and continually recreating RotateBack() closures, something weird is going on.
that’s about as far as i got - it’s probably not truly “hard” to solve, but you can only expect so much from “free” help (in other words, i must move on to “real” work now :D)
Yes, it seems that I need both the spheres and the box moving to produce the error. In my opinion the box rotation does not grow anywhere. Both memory consumption and cpu usage stay static. Anyway, thanks davebollinger for your input. Let’s hope this will be fixed soon!
You can check the memory in the console with this snippet:
local function checkMemory() collectgarbage( "collect" ) local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) ) print( memUsage\_str, "TEXTURE = "..(system.getInfo("textureMemoryUsed") / (1024 \* 1024) ) ) end timer.performWithDelay( 5000, checkMemory, 0 )
Thanks for the snippet chagano!
Good news! This has been fixed in daily build 2014.2188.