Corona Enterprise Supports Manual Image Loading?

One of the reasons I decided in the past to switch away from Corona, is that this application (made with Corona): https://play.google.com/store/apps/details?id=com.kidoteca.nonoamazonia.beta crashes a lot. Mostly because of memory management issues.

Corona Enterprise would allow me to keep this source code, but instead of loading the images with Corona allowing me to load in whatever way I want? And this way handle the memory the way I want (and skip Lua GC, and maybe even Java GC on Android…)

Maurício Gomes

Kidoteca

Anyone?

Stan,

If you want to load images into Corona’s OpenGL view, then you have to go through Corona’s APIs.

Now, if you want to load images on top of Corona’s OpenGL view, outside of Corona’s display object system, then you can load them yourself and display them via Android’s ImageView class in Java.  You can then add the ImageView to the CoronaActivity’s overlay view, which is made available via the following method…

http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaActivity.html#getOverlayView()

But that said, our image loading code actually has a lot of fallback mechanisms to make it work on a wide range of Android devices.  If we discover that the image is too big to load due to out of heap space in Java or it is beyond the max texture size in OpenGL, then we automatically down-sample/scale the image.  If we still can’t load the image due to out-of-memory, then we force garbage collection and try to load the image again.  If the image still fails to load, then we have no choice but to log the error and return “nil” from display.newImage() or display.newImageRect().

Typically these image loading crashes that you’ve heard about are not coming from Corona’s image loading code, but caused by the Corona developer’s Lua script attempting to use a “nil” object returned by display.newImage() because we were unable to load the image… which typically happen when we run out of memory.  There’s nothing we can do on our end when memory runs out on the device.

(However, if you do discover that a crash is coming from our code, then please let us know.)

Now, there is one other solution that you should try out if you are running into OutOfMemory exceptions.  You can request the Android OS to give your app a larger heap by adding the “largeHeap” attribute to your AndroidManifest.xml file’s “application” tag as documented by Google here…

http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap

You can also enable large heap support via Corona Simulator builds by modifying your “build.settings” file as documented here…

http://developer.coronalabs.com/forum/2012/08/07/very-weird-texture-memory-problem-android#comment-136404

We’ve received confirmation from other Corona developers that setting “largeHeap” to true has solved their out of memory errors.

Anyways, I hope this helps!

Actually, our app is working mostly fine on Android.

It is crashing like crazy on iOS, every time we load something new, and the crash is caused by out of memory errors. It is not entirely unexpected by me, because iPad1 and iPad3 both have terrible amounts of memory in relation to their resolution.

Right now the “solution” is a almost constant calling of the garbage collector when unloading anything. But some iOS devices still crash like crazy.

The simulator does not crash at all.

Hi @stan8,

As you have presumed, this is likely a texture memory issue on these devices. Have you run a texture memory check function to monitor your memory?

[lua]

local function memPrinting()
  collectgarbage(“collect”)
  local memUsage_str = string.format( “MEMORY = %.3f KB”, collectgarbage( “count” ) )
  print( memUsage_str, "TEXTURE = "…(system.getInfo(“textureMemoryUsed”)/1048576) )
end
timer.performWithDelay( 1000, memPrinting, 0 )

[/lua]

Additionally, are you using “typical” texture memory management procedures? For example, using image sheets + a texture packing utility, and keeping to the lowest-possible Power of 2 values? As you probably know, one of the issues with the Retina iPads is that designing equivalent images will take up 4x the texture memory, but of course the iPad3/4 doesn’t have 4x the texture memory as non-Retina iPads. This is an unfortunate double-edged sword… stunning sharp display, but harder for developers to keep within the memory envelope.

Regards,

Brent

Hello Brent,

Well, actually we do use TexturePacker, smallest possible pot textures, and it was using the code that you pasted that I figured that one problem was with GC.

The code that you made, when you remove the “collectgarbage(“collect”)” line (that affects the results when you want to track the GC) we got the following:

Level loads. memory use is around 150mb (on iPad Retina)

request second level.

storyboard triggers unloading of first level, and loading of second… memory use jumps to 300mb…

if the device did not crashed the 300mb memory use, some seconds later, it returns to 150mb

So clearly, the garbagecollector is too slow. Now I call it every time I unload something, and crashes got greatly reduced, but memory related crashes still happen.

Lua garbage collection can be an expensive operation, so this is actually the desired behavior.  Having Corona force garbage collection on every remove() call would have a negative performance impact.  So, I would so what you are doing, invoking garbage collection yourself after removing the entire scene, is the best approach.

If you are still running out of memory even after forcing garbage collection, then the issue is exactly that, you are loading too many images into memory than that device can handle.  Unfortunately, there is no OpenGL API for determining how much texture memory the device has.  This is an OpenGL limitation.  But that said, many developers have been able to successfully guess how much memory the device has based on its max texture size.  Typically, if the device has a low max texture size (say 1024x1024), then you have to assume the device has very little texture memory and you should use low res images.

You can fetch the device’s max texture size as follows…

   local maxTextureSize = system.getInfo(“maxTextureSize”)

http://docs.coronalabs.com/api/library/system/getInfo.html#maxtexturesize

Anyone?

Stan,

If you want to load images into Corona’s OpenGL view, then you have to go through Corona’s APIs.

Now, if you want to load images on top of Corona’s OpenGL view, outside of Corona’s display object system, then you can load them yourself and display them via Android’s ImageView class in Java.  You can then add the ImageView to the CoronaActivity’s overlay view, which is made available via the following method…

http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaActivity.html#getOverlayView()

But that said, our image loading code actually has a lot of fallback mechanisms to make it work on a wide range of Android devices.  If we discover that the image is too big to load due to out of heap space in Java or it is beyond the max texture size in OpenGL, then we automatically down-sample/scale the image.  If we still can’t load the image due to out-of-memory, then we force garbage collection and try to load the image again.  If the image still fails to load, then we have no choice but to log the error and return “nil” from display.newImage() or display.newImageRect().

Typically these image loading crashes that you’ve heard about are not coming from Corona’s image loading code, but caused by the Corona developer’s Lua script attempting to use a “nil” object returned by display.newImage() because we were unable to load the image… which typically happen when we run out of memory.  There’s nothing we can do on our end when memory runs out on the device.

(However, if you do discover that a crash is coming from our code, then please let us know.)

Now, there is one other solution that you should try out if you are running into OutOfMemory exceptions.  You can request the Android OS to give your app a larger heap by adding the “largeHeap” attribute to your AndroidManifest.xml file’s “application” tag as documented by Google here…

http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap

You can also enable large heap support via Corona Simulator builds by modifying your “build.settings” file as documented here…

http://developer.coronalabs.com/forum/2012/08/07/very-weird-texture-memory-problem-android#comment-136404

We’ve received confirmation from other Corona developers that setting “largeHeap” to true has solved their out of memory errors.

Anyways, I hope this helps!

Actually, our app is working mostly fine on Android.

It is crashing like crazy on iOS, every time we load something new, and the crash is caused by out of memory errors. It is not entirely unexpected by me, because iPad1 and iPad3 both have terrible amounts of memory in relation to their resolution.

Right now the “solution” is a almost constant calling of the garbage collector when unloading anything. But some iOS devices still crash like crazy.

The simulator does not crash at all.

Hi @stan8,

As you have presumed, this is likely a texture memory issue on these devices. Have you run a texture memory check function to monitor your memory?

[lua]

local function memPrinting()
  collectgarbage(“collect”)
  local memUsage_str = string.format( “MEMORY = %.3f KB”, collectgarbage( “count” ) )
  print( memUsage_str, "TEXTURE = "…(system.getInfo(“textureMemoryUsed”)/1048576) )
end
timer.performWithDelay( 1000, memPrinting, 0 )

[/lua]

Additionally, are you using “typical” texture memory management procedures? For example, using image sheets + a texture packing utility, and keeping to the lowest-possible Power of 2 values? As you probably know, one of the issues with the Retina iPads is that designing equivalent images will take up 4x the texture memory, but of course the iPad3/4 doesn’t have 4x the texture memory as non-Retina iPads. This is an unfortunate double-edged sword… stunning sharp display, but harder for developers to keep within the memory envelope.

Regards,

Brent

Hello Brent,

Well, actually we do use TexturePacker, smallest possible pot textures, and it was using the code that you pasted that I figured that one problem was with GC.

The code that you made, when you remove the “collectgarbage(“collect”)” line (that affects the results when you want to track the GC) we got the following:

Level loads. memory use is around 150mb (on iPad Retina)

request second level.

storyboard triggers unloading of first level, and loading of second… memory use jumps to 300mb…

if the device did not crashed the 300mb memory use, some seconds later, it returns to 150mb

So clearly, the garbagecollector is too slow. Now I call it every time I unload something, and crashes got greatly reduced, but memory related crashes still happen.

Lua garbage collection can be an expensive operation, so this is actually the desired behavior.  Having Corona force garbage collection on every remove() call would have a negative performance impact.  So, I would so what you are doing, invoking garbage collection yourself after removing the entire scene, is the best approach.

If you are still running out of memory even after forcing garbage collection, then the issue is exactly that, you are loading too many images into memory than that device can handle.  Unfortunately, there is no OpenGL API for determining how much texture memory the device has.  This is an OpenGL limitation.  But that said, many developers have been able to successfully guess how much memory the device has based on its max texture size.  Typically, if the device has a low max texture size (say 1024x1024), then you have to assume the device has very little texture memory and you should use low res images.

You can fetch the device’s max texture size as follows…

   local maxTextureSize = system.getInfo(“maxTextureSize”)

http://docs.coronalabs.com/api/library/system/getInfo.html#maxtexturesize