Memory Management with display.newImage() is broken!

I understand that Corona does seem to cache and reuse images loaded from the same path in some way even if it was removed from the viewport. So the question is: What happens if I use all different images!?

To test this I wrote some simple test code which will duplicate the “test.jpg” you place into your project directory 300 times into the documents folder of the app and shows every single copy for 1 second and remove it afterward.

-- creating copies of an image file to test memory behaviour  
  
-- reading source file from resources  
io.output():setvbuf('no')  
  
-- read imagedate for later  
local fname=system.pathForFile("test.jpg", system.ResourceDirectory)  
local fh=io.open(fname,'rb')  
local imagedata=fh:read('\*a')  
io.close(fh)  
  
function createCopy(i)  
 -- creating a copy if not existing  
 local iname="iapp\_test5\_"..i..".jpg"  
 local ipath=system.pathForFile(iname, system.DocumentsDirectory)  
 local fh=io.open(ipath,'rb')  
 if fh then  
 -- file existing  
 io.close(fh)  
 else  
 print("Create image "..i)  
 local fh=io.open(ipath,'wb')  
 fh:write(imagedata)  
 io.close(fh)  
 end  
 return iname  
end  
  
do  
local frame=0  
local image=1  
local max=300  
  
function render(event)  
 frame=frame+1  
  
 if frame == 1 then  
 local iname=createCopy(image)  
 print("Adding an image "..iname)  
 local r=display.newImage(iname,system.DocumentsDirectory)  
 image=image+1  
 if image \> max then  
 image=1  
 end  
 elseif frame == 30 then  
 print("Removing the image in stage")  
 local s=display:getCurrentStage()  
 s:remove(s[1])  
 --local x=s:remove(s[1])  
 --x=nil  
 frame=0  
 end  
end  
  
Runtime:addEventListener( "enterFrame", render )  
  
end  

I am using the device console and instruments to trac the program running on my iPhone.

It WILL eat a lot of memory while running… I had it collect about 32 MB of memory down back to 6 at about picture 30

After 76 pictures the console started to print low memory warnings and “mail” was asking to exit

(which launchd tried to restored immediately)

At 83 it asked “telephone” to quit… and short afterwards the test app was killed

Afterwards the test applicaton could not be started again!!!

I had to reset the iPhone to get it running again!

INTERESTING: Sometimes! It collects after the first memory warning… sometimes not. My very first run of this program was shrinking memory usage after about 30 pics back to 6 MB from 49 MB. Later runs of the same program did not do it! I wonder if the treshold Corona may use for its texture/globject cache is just to low to generate a stable behaviour?

So there is something wrong with Corona in this aspect!

P.S.: The commented out code is just a reference to another thread here… will not change anything… so don’t take that serious :)) [import]uid: 6928 topic_id: 1251 reply_id: 301251[/import]

Additional info! I just saw that the first runs log is showing this after 30 images:

Fri Jun 18 13:38:30 unknown UIKitApplication:EmptyTest[0xcf04][89] <notice>: Adding an image iapp_test5_31.jpg<br>Fri Jun 18 13:38:30 unknown SpringBoard[25] <notice>: MultitouchHID(208bc0) uilock state: 0 -&gt; 1<br>Fri Jun 18 13:41:08 unknown SpringBoard[25] <notice>: MultitouchHID(208bc0) uilock state: 1 -&gt; 0<br>Fri Jun 18 13:41:09 unknown SpringBoard[25] <notice>: MultitouchHID(2e8da50) device bootloaded<br>Fri Jun 18 13:41:13 unknown UIKitApplication:EmptyTest[0xcf04][89] <notice>: Removing the image in stage<br>Fri Jun 18 13:41:13 unknown UIKitApplication:EmptyTest[0xcf04][89] <notice>: Adding an image iapp_test5_32.jpg<br>

This is the “crash” of the first run I made (pretty devastating … hehe)

<br>Fri Jun 18 13:25:48 unknown UIKitApplication:EmptyTest[0x52da][5582] <notice>: Create image 81<br>Fri Jun 18 13:25:48 unknown UIKitApplication:EmptyTest[0x52da][5582] <notice>: Adding an image iapp_test5_81.jpg<br>Fri Jun 18 13:25:53 unknown UIKitApplication:EmptyTest[0x52da][5582] <notice>: Removing the image in stage<br>Fri Jun 18 13:25:53 unknown UIKitApplication:EmptyTest[0x52da][5582] <notice>: Create image 82<br>Fri Jun 18 13:25:53 unknown UIKitApplication:EmptyTest[0x52da][5582] <notice>: Adding an image iapp_test5_82.jpg<br>Fri Jun 18 13:25:58 unknown configd[23] <notice>: jetsam: kernel memory event (91), free: 780, active: 2328, inactive: 2452, purgeable: 0, wired: 16600<br>Fri Jun 18 13:25:58 unknown SpringBoard[25] <warning>: Memory level is urgent (9%) and there are no background apps to ask to exit.<br>Fri Jun 18 13:25:59 unknown configd[23] <notice>: jetsam: kernel termination snapshot being created<br>Fri Jun 18 13:25:59 unknown com.apple.launchd[1] <notice>: (UIKitApplication:com.apple.mobilephone[0x4e29]) Exited: Killed<br>Fri Jun 18 13:25:59 unknown com.apple.launchd[1] <notice>: (UIKitApplication:EmptyTest[0x52da]) Exited: Killed<br>Fri Jun 18 13:25:59 unknown SpringBoard[25] <warning>: Application 'Telefon' exited abnormally with signal 9: Killed<br>

Later runs killed the app earlier! I love reading logs… better that any Stephen King Horror story!

<br>Fri Jun 18 13:49:18 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 32<br>Fri Jun 18 13:49:18 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_32.jpg<br>Fri Jun 18 13:49:23 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Removing the image in stage<br>Fri Jun 18 13:49:23 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 33<br>Fri Jun 18 13:49:23 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_33.jpg<br>Fri Jun 18 13:49:27 unknown configd[23] <notice>: jetsam: kernel memory event (90), free: 709, active: 3812, inactive: 2252, purgeable: 0, wired: 15450<br>Fri Jun 18 13:49:27 unknown com.apple.launchd[1] <notice>: (com.apple.mediaserverd) Exited: Killed<br>Fri Jun 18 13:49:27 unknown SpringBoard[25] <warning>: Memory level is urgent (10%). Asking 'iPod' to exit.<br>Fri Jun 18 13:49:27 unknown MobileMusicPlayer[49] <warning>: _serverConnectionDiedNotification. Info -- notification=NSConcreteNotification 0x11c2a0 {name = AVController_ServerConnectionDiedNotification; object = <avcontroller:>}, AVController = <avcontroller:>, currentTime = 0.00<br>Fri Jun 18 13:49:28 unknown com.apple.launchd[1] <warning>: (UIKitApplication:com.apple.mobileipod[0xcdc5]) Exited with exit code: 101<br>Fri Jun 18 13:49:28 unknown com.apple.launchd[1] <warning>: (UIKitApplication:com.apple.mobileipod[0xcdc5]) Throttling respawn: Will start in 2147482805 seconds<br>Fri Jun 18 13:49:28 unknown SpringBoard[25] <warning>: Application 'iPod' exited abnormally with exit status 101<br>Fri Jun 18 13:49:29 unknown SpringBoard[25] <warning>: Memory level is urgent (10%). Asking 'Mail' to exit.<br>Fri Jun 18 13:49:29 unknown CommCenter[29] <notice>: PersConn-MobileMail-xxxx is releasing its assertion on PDP context 0.<br>Fri Jun 18 13:49:29 unknown CommCenter[29] <notice>: MobileMail is releasing its assertion on PDP context 0.<br>Fri Jun 18 13:49:29 unknown com.apple.launchd[1] <warning>: (UIKitApplication:com.apple.mobilemail[0x6a5a]) Exited with exit code: 101<br>Fri Jun 18 13:49:29 unknown SpringBoard[25] <warning>: Application 'Mail' exited abnormally with exit status 101<br>Fri Jun 18 13:49:29 unknown SpringBoard[25] <warning>: Memory level is not normal (10%). Delaying auto-relaunch of 'Mail' for 30 seconds.<br>Fri Jun 18 13:49:29 unknown SpringBoard[25] <warning>: Memory level is urgent (10%) and there are no background apps to ask to exit.<br>Fri Jun 18 13:49:35 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Removing the image in stage<br>Fri Jun 18 13:49:35 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 34<br>Fri Jun 18 13:49:35 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_34.jpg<br>Fri Jun 18 13:49:41 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Removing the image in stage<br>Fri Jun 18 13:49:41 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 35<br>Fri Jun 18 13:49:41 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_35.jpg<br>Fri Jun 18 13:49:44 unknown configd[23] <notice>: jetsam: kernel memory event (90), free: 709, active: 3838, inactive: 2209, purgeable: 0, wired: 16000<br>Fri Jun 18 13:49:44 unknown SpringBoard[25] <warning>: Memory level is urgent (10%) and there are no background apps to ask to exit.<br>Fri Jun 18 13:49:52 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Removing the image in stage<br>Fri Jun 18 13:49:52 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 36<br>Fri Jun 18 13:49:52 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_36.jpg<br>Fri Jun 18 13:49:57 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Removing the image in stage<br>Fri Jun 18 13:49:57 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Create image 37<br>Fri Jun 18 13:49:57 unknown UIKitApplication:EmptyTest[0x8668][117] <notice>: Adding an image iapp_test5_37.jpg<br>Fri Jun 18 13:50:00 unknown kernel[0] <debug>: launchd[120] Builtin profile: MobileMail (seatbelt)<br>Fri Jun 18 13:50:02 unknown configd[23] <notice>: jetsam: kernel memory event (90), free: 709, active: 4041, inactive: 2100, purgeable: 0, wired: 16747<br>Fri Jun 18 13:50:02 unknown SpringBoard[25] <warning>: Memory level is urgent (10%). Asking 'Mail' to exit.<br>Fri Jun 18 13:50:02 unknown com.apple.launchd[1] <warning>: (UIKitApplication:com.apple.mobilemail[0x8134]) Exited with exit code: 101<br>Fri Jun 18 13:50:02 unknown SpringBoard[25] <warning>: Application 'Mail' exited abnormally with exit status 101<br>Fri Jun 18 13:50:02 unknown SpringBoard[25] <warning>: Memory level is not normal (10%). Delaying auto-relaunch of 'Mail' for 30 seconds.<br>Fri Jun 18 13:50:02 unknown SpringBoard[25] <warning>: Memory level is urgent (10%) and there are no background apps to ask to exit.<br>Fri Jun 18 13:50:05 unknown com.apple.launchd[1] <notice>: (UIKitApplication:com.apple.mobilephone[0x6962]) Exited: Killed<br>Fri Jun 18 13:50:05 unknown com.apple.launchd[1] <notice>: (UIKitApplication:EmptyTest[0x8668]) Exited: Killed<br>Fri Jun 18 13:50:05 unknown configd[23] <notice>: jetsam: kernel termination snapshot being created<br>Fri Jun 18 13:50:06 unknown SpringBoard[25] <warning>: Application 'Telefon' exited abnormally with signal 9: Killed<br>Fri Jun 18 13:50:06 unknown DTMobileIS[114] <warning>: DTLeaksService encountered an error while attempting to analyze pid: 117<br>task_resume (task_stop_peeking) failed. (DTLeaksService)<br>Fri Jun 18 13:50:06 unknown SpringBoard[25] <warning>: Application 'EmptyTest' exited abnormally with signal 9: Killed<br>Fri Jun 18 13:50:07 unknown ReportCrash[121] <error>: Saved crashreport to /Library/Logs/CrashReporter/LowMemory-2010-06-18-135007.plist using uid: 0 gid: 0, synthetic_euid: 0 egid: 0<br>Fri Jun 18 13:50:33 unknown kernel[0] <debug>: launchd[124] Builtin profile: MobileMail (seatbelt)<br>

Again… there is something wrong with Corona :frowning: [import]uid: 6928 topic_id: 1251 reply_id: 3294[/import] </avcontroller:></avcontroller:>

I was just forced (kinda) to look into this topic again. Here are my new finds:

Those leaking / crashing is totally different with 4 devices I tested:

  1. iPhone 3GS with 3.1.3 … exposes the behavior of my first post!

  2. iPad with 3.2… WORKS you see “low memory warnings” in debug output for the test app and it frees memory then. This will happen after about 20-25 MB used!

  3. iPod Touch with 3.1.3 … will free it’s memory directly… no warning to see. Really… it was never going over 10 MB while testing. But it also runs very very slow…

  4. Phone 3GS with 4.0 GM … crashes too! I was thinking something fixed it in iOS 3.2 but either it does not … or its different in 4.0 again

I have exactly the same App on all devices… (the code from my first post)

As I write here… the iPad is still runnung this program (at image 130 now) whereas the iPhone did crash with it multiple times with image at 20-30 now!

I will let the iPod run for some time too… it is working for about 30 minutes already without the crash too

So basically … this code does only crash on iPhone for me… 3.1.3 or 4.0 does not matter it seems… [import]uid: 6928 topic_id: 1251 reply_id: 3331[/import]

I’m wondering if part of the problem is the amount of memory taken up by the 300 images your are creating in the folder. This may account for some of the low memory warnings and the different behavior on different devices.

Did anything change when you added the “x=nil” code?

Anyway, just a thought.

Tom [import]uid: 6119 topic_id: 1251 reply_id: 3332[/import]

I would assume if you’re doing something like that you need to be much more mindful of the garbage collector. As far as I know, the garbage collector can run at any time and there’s no guarantee of when it will run. This means if you’re doing something like that, adding a lot of images, you should make sure the garbage is collected and doesn’t stick around in memory. Try putting collectgarbage(“collect”) somewhere that will run fairly frequently to make sure there’s never too much garbage. This might slow it down a little, but it will assure you don’t run out of memory… [import]uid: 6678 topic_id: 1251 reply_id: 3333[/import]

@fogview

No it isn’t … The iPhone crashes when very few images are created and I have apps which keep much more data in its docs area. I have multiple GB free on that Device too.

The iPhone and the iPod have 256 MB RAM … Sadly the iPad too … This is not used for the images I create in the documents folder.

It does not change anything with the nil :wink: … Even thinking it could, would mean Lua is totally brocken in respekt of reference counting. And Lua is pretty good with that.

In fact the memory in question is not even allocated by lua… And not deallocated by Lua either. I am sure ansca has a cache and is purging that at special occasion … But only if there is no lua reference left.

The devs will know… [import]uid: 6928 topic_id: 1251 reply_id: 3334[/import]

Double post… The Forum Server has hickups … [import]uid: 6928 topic_id: 1251 reply_id: 3337[/import]

@dfox

My first testcode had calls to collect garbage… But this was removed as I found that Lua does not allocates the data for the images. The lua memory stays constant (hence my running gag with that nil…)

The problem lies in the cache corona uses to optimize image loading and reusage. I bet they act on requests by the system to free memory so they can use the maximum possible amount. But something seems to go wrong for the iPhone … Try the testcode with instrumenrs attached and you see what i mean.

The whole fragility of the collector people talk about in the forum has to do with framerate drops. The collector works perfectly even with thousands of objects. The thing which bugs people has to do with timing. just enter a “step” per frame and it will stay smooth usually. [import]uid: 6928 topic_id: 1251 reply_id: 3336[/import]

Ah, I see. I take your word for it but maybe I’ll give it a try later when I have some time. [import]uid: 6678 topic_id: 1251 reply_id: 3340[/import]

Would any person from ansca write something about this topics please? [import]uid: 6928 topic_id: 1251 reply_id: 3458[/import]

It could be that the texture memory is not released properly (glDeleteTexture). Anyway, this seems to be most likely engine related and not something that is LUA related, unless you didn’t remove all references.

What I am wondering about is how Corona work internal in this field. Does Corona only check for not used textures when you remove a display object from its parent? Or does it check periodically, maybe before each frameevent? [import]uid: 5712 topic_id: 1251 reply_id: 3460[/import]

As you may see in the logs I posted… when it works it frees the memory when the system issues a low memory warning to the application… for some reason this seems to fail on my iPhone (both with the last 3 and 4 iOS).

It works and is traceable with instruments and logging on iPad and iPod touch … so I expect it to be a race condition of some kind.

I guess they check for active reverences from lua and if none is there they may free the memory. The caching itself seems to be done by the image name… which by itself could be a problem if you have changing images with the same name. But I did not test for that so far… (it is an assumption because of the documentation of the function) [import]uid: 6928 topic_id: 1251 reply_id: 3461[/import]

Corona has a low-memory handler which gets notified by the iPhone to free memory. In these situations, we force a Lua GC. Any display objects that do not have Lua references are freed, including texture memory (assuming no other live display objects use the same image file). Corona must do so in a limited time period or else the iPhone will forcibly quit the app (i.e. crash the app).

In your example, you are doing file duplications of an existing image which is an I/O bound task. It’s very likely that Corona is blocked from receiving the low-memory notification from the iPhone, b/c it’s still busy inside the Lua block performing the file duplication — race conditions prevent us from operating on the Corona state to free memory while we’re inside Lua. Of course, the timing may sometimes work out, so that memory does get freed in time by our low-memory handler, which is something you may have observed.

In the short term, it’s generally a good idea not to rely on these “emergency” features, but to explicitly handle the management, by removing display objects from the stage and also ensuring all references to that object are nil’d.

In the long run, we’re investigating how to reduce the impact of the latter (nil’ing references to display objects). The idea is to be more aggressive about freeing memory associated with display objects. A display object is just a Lua table with special behavior added on top (properties, methods, and underlying resources).

So one idea is if a display object is no longer on the stage at the end of a Lua chunk (e.g. a listener removes the display object but doesn’t re-insert it), then strip away all the special behavior, so it’s just a plain table. This way we can free up associated memory like textures more aggressively. We also gracefully handle situations where the Lua code still has accidental references to this display object — in the worst case, the memory hit is the memory consumed by a Lua table.

Another complementary idea is to manage the texture memory in a LRU scheme. The downside is that this competes with pre-loading images. [import]uid: 26 topic_id: 1251 reply_id: 3471[/import]

@walter

Nice to get some more insight to this topic!

“In the short term, it’s generally a good idea not to rely on these “emergency” features, but to explicitly handle the management, by removing display objects from the stage and also ensuring all references to that object are nil’d.” …

… So I did something wrong? Please correct my code! Show me how to do what you wrote there!

I really still wonder about that whole “nil’ing” stuff… now from you… elaborate please!!!

And please somebody explain me how to NIL a table… :slight_smile: … the Lua memory for a table can’t be actively nil’ed or free’d … stop telling that you can “nil” an object. It is not true. You can remove all it’s references by setting their variables to nil or by letting them leave the scope.

The table still exists till GC removes it. Then it is free’d… and not niled :slight_smile:

You seem to keep a cache with loaded images… and don’t free it at that time… thats the only explanation for what I see when I use instruments / console on the iPhone to investigate the behaviour.

I can’t make my example code work better by forcing GC every frame… It still crashes and uses the memory it does without calling

Following Code does (imho) proof that you do NOT allocate memory of display object together with the lua objects… and you do not free it together with the lua objects…

io.output():setvbuf('no')  
  
local i=0  
function frames(event)  
 local t=system.getTimer()  
 collectgarbage('collect')  
 local mem1=collectgarbage('count')  
 local img=display.newImage("test.jpg",i%200,i%200)  
 img.parent:remove(img)  
 -- img=nil -- (not needed really)  
 collectgarbage('collect')  
 print(i..": "..(system.getTimer()-t)..' m1:'..mem1..' m2:'..collectgarbage('count'))  
 i=i+1  
end  
  
-- try it while not exiting lua code  
for i=1,120 do  
 frames()  
end  
  
-- try it while exiting lua code  
Runtime:addEventListener( "enterFrame", frames )  

My utilization of the IO to create the copies in my original test does not create the problem and may not even make it worse as you maybe see I “wait” between copy and display. There is enough time for the handler to warn before the next file gets copied (1 Frame… you could set it to any number for testing that btw)

The test code crashes on consecutive run even if the files are already generated. I also have reproducable behaviour that it works on iPod Touch… and iPad but not on the iPhone… every time I test it!

Of course I can only test with my hardware… but I found it strange that it is the same for 4 and 3 of iOS on the iPhone … but and behaves totally different on the iPod Touch (seems not to cache any images at all… memory does not grow!)
While reading this first part I wonder “what I did wrong” (and hence it does not qualify as bug in the SDK)… I wonder about the remaining part…

For sure I won’t rely on emergency features… I believe Corona does… in the current implementation!

So whats the word about it? Is my code wrong? Or is it a bug? What to do?

BTW: MY solution would be that we can simply tell Corona which texture we want to cache and which we don’t want to be cached!

We could do this with a simple member variable …

Another solution would be to be able to mark image objects for early deallocation by specifying a parameter to obj.parent:remove(obj ,true) which would mark the “image texture” memory to be purged at the next Lua GC which could be triggered under our control!

The less elegant version would be a function to deallocate the memory of the underlying object… which would render this display object “defunctional” before lua does destroy its memory. [import]uid: 6928 topic_id: 1251 reply_id: 3474[/import]

@walter

You wrote: “Any display objects that do not have Lua references are freed, including texture memory …”

Can you please clarify the following concerning objects removed from a group and when they are freed? Here is some sample code where three objects (a, b, c) are added to the current stage and then removed.

do  
local a = display.newRect(0, 0, 20, 20)  
local b = display.newRect(20, 20, 20, 20)  
print ("a object: " .. tostring(a) )  
print ("b object: " .. tostring(b) )  
end  
  
local c = display.newRect(0, 100, 50, 50)  
print ("c object: " .. tostring(c) )  
  
local stage = display.getCurrentStage()  
  
stage:remove(c) -- Remove object "c"  
local d = stage:remove(1) -- Remove object "a"  
stage:remove(1) -- Remove object "b"  
  
print ("d object: " .. tostring(d) )  
print ("c object: " .. tostring(c) )  

Before the objects were removed:

  • Objects “a” and “b” are what I call headless objects – they exist in the group (main stage) but no longer referenced by a variable (except by group index).
  • Object “c” exist in the group and also referenced by variable “c”

After the objects are removed:

  • Object “a” is still around (removed but now referenced by variable “d”)
  • Object “b” is gone (removed and no reference)
  • Object “c” is still around (removed but still referenced by variable “c”)

Setting variables “a” and “c” = nil would remove the reference and therefore freed up the memory used?

Is this correct?

Thanks,
Tom [import]uid: 6119 topic_id: 1251 reply_id: 3478[/import]

I think you mean:

Setting variables “d” (not a) and “c” = nil would remove the reference and therefore freed up the memory used?

And I think you are basically correct! At least for any lua memory involved…

But I think that the “stage” is a kind of real lua table (object) too… so your headless objects are “lua” referenced (when I am right about the implementation of corona display objects)

You can validate your thiking by using collectgarbage(“collect”) print(collectgarbage(“count”)) at the different steps. For “rect” objects there seems to be more or less only lua memory being allocated.

which boils down to:

collectgarbage("collect")  
print(collectgarbage("count"))  
local a = display.newRect(0,0,100,100)  
collectgarbage("collect")  
print(collectgarbage("count"))  
a.parent:remove(a)  
collectgarbage("collect")  
print(collectgarbage("count"))  
a=nil  
collectgarbage("collect")  
print(collectgarbage("count"))  

or…

do  
collectgarbage("collect")  
print(collectgarbage("count"))  
local a = display.newRect(0,0,100,100)  
collectgarbage("collect")  
print(collectgarbage("count"))  
a.parent:remove(a)  
collectgarbage("collect")  
print(collectgarbage("count"))  
end  
collectgarbage("collect")  
print(collectgarbage("count"))  

But… My concerns are not about lua memory… but about the memory taken up by the preloaded images (even if nothing refers to them anymore)

To view this memory you can’t use anything but “Instruments” attacked to the app running on the real device. There it is quiet obvious… we should focus on this memory… lua’s garbage collector is well working… :slight_smile: [import]uid: 6928 topic_id: 1251 reply_id: 3479[/import]

@OderWat

“think you mean:
Setting variables “d” (not a) and “c” = nil would remove the reference and therefore freed up the memory used?”

Yes, I did mean “d” and not “a”.

The “headless” reference was because variables “a” and “b” were local to the do…end chunk. The objects are still referenced in the main stage (Lua table) so my question was what happens to the objects when removed.


I realize that this doesn’t apply to your “preloaded images” problem but I thought it would be good to get an answer since Walter mentioned it.

Thanks,
Tom [import]uid: 6119 topic_id: 1251 reply_id: 3480[/import]

@Oderwat, your new version (06/25) will likely crash on iPhone b/c the startup time is limited. If main.lua doesn’t complete within some time slice on launch, iPhone will force quit your app.

Also, collectgarbage only accounts for memory consumed by Lua, not by the graphics system of Corona, i.e. textures. Hence, you will not see much difference. [import]uid: 26 topic_id: 1251 reply_id: 3483[/import]

For removal, you should use the removeSelf() method, e.g. “c:removeSelf()”, b/c not all objects are children of the stage object

In your case, “c” will be GC’d, since there are no more references to c. If “c” had been global (no local declaration), it would live forever, and thus not be a candidate for being freed.

The issue becomes more salient when you stick “c” as a property of a parent group for convenience (as indices are fragile):

local parent = display.newGroup()  
local a = display.newRect( 0, 0, 20, 20 )  
  
parent:insert( a )  
parent.rectangle = a  
  
a:removeSelf()   

In the above case, b/c “parent.rectangle” still refers to the rectangle display object, we cannot free it.
[import]uid: 26 topic_id: 1251 reply_id: 3484[/import]

@walter

  1. That is no “new” version but an demonstration that Corona does only load an image one! once because all but the first “newImage” calls do not need any time. In addition they do not change the memory consumption in Lua nor in the device itself (Instruments can tell).

  2. You say my version will “likely crash” … NO, it does not crash!

Are we into guesstimating Why Do I write examples? This is the Bug Report forum!

You did not test any of the code I wrote here right?

This little demo code uses near not time at all for generating the inidial 120 image objects.

If that code fragment would crash… we all where in big trouble writing working programs!

See it running:

Sat Jun 26 11:28:44 unknown UIKitApplication:EmptyTest[0x05][4495] <notice>: 3722: 2 m1:48.6826171875 m2:48.7685546875<br>

3. I was demonstrating that GC only accounts for Lua memory many times before. This is not a topic (of me)

4. To Remind you: Topic is "Bug in the Memory Management of Coronas graphics system"
5 … about you last post:

c.parent:remove© … is identical to c:removeSelf()… right?
But that will not change the fact that removeSelf() is not documented anywhere in your documentation and is just mentioned once in the Game Edition SDK.

The Documented way is:

"group:remove( indexOrChild ) Removes from group the display object specified by indexOrChild, shifting down other elements as needed. The argument indexOrChild is either the index position of the child within group or the child display object itself. In either case, it returns the removed display object."

In addition… his “c” is not getting freed… the local scope of main.lua is not freed till the program ends …

So please (anybody else!)…

Correct my OP code and / or file this as bug and correct the SDK! [import]uid: 6928 topic_id: 1251 reply_id: 3485[/import]