Very weird texture memory problem on Android

Just tried our app on on a Sony Tablet S (SGPT111), android 4.0.3 with the following results:

Corona Build 868:
Game loaded successfully

Corona build 971:
Crashed, out of memory followed by a segfault. It also crashes on other scenes with similarly sizes spritesheets.

Looking at the logs, one unusual detail is that in Build 971 it runs out of memory while using 19770K/39669K of heap. But in build 868 the app immediately starts out with a limit of 48647K heap memory and grows up to a max of 39866K/48647K on the offending sprite-sheet, then continues working just fine.

I opened up adb shell on this device and ran dumpsys meminfo on the Corona process and the data seems to add to theory that the device is allocating less max heap to apps built with newer versions of Corona.

Here’s the output I got:
https://gist.github.com/2e23fcaa183de2ca4648 [import]uid: 135827 topic_id: 29558 reply_id: 131984[/import]

Hmm… I’m getting the impression that the Kindle Fire HD has a lazy garbage collector, because a 64 MB maximum heap size “is” big enough to load 2048x2048 images. And you may be right about the [lua]sprite.newSpriteSheetFromData()[/lua] function causing the crash because it may not be handling the case where the image fails to load, unlike our other functions. I personally haven’t tested for this case myself with our newest sprite API.

Would you two mind sending us your Corona projects so that we can reproduce this issue for ourselves? You can do so by clicking the “Report a Bug” link at the top of this page. Make sure to mention this forum thread and my name so that our tech-support group knows to talk to me about it when they receive your bug report.

Oh and I hope I didn’t come across as difficult. Every once in a while we do get tech-support issues about out-of-memory errors, but they’re usually not Corona issues and are really because the app is attempting to load too many images; more than a low-end Android device is capable of storing in memory. But I’m always willing to be convinced otherwise. :slight_smile:

And in case you are interested, the reason why Corona is able to load your images without issues on a low-end Droid or Nook device is because Corona actually looks at the max heap size, calculates the memory needed to load the image, and automatically lowers the color quality and/or down-samples the image so that it can load it into memory. We really went well out of our way to make image loading as robust as possible. Especially on low-end devices, of which there are too many. So, I hope this gives you some confidence. It just looks we need to take care of this one last thing.
[import]uid: 32256 topic_id: 29558 reply_id: 131987[/import]

George,

In my experience, the max heap size is set by the device. It does not change when building your app against different Android API Levels, which is the only real difference between Corona build #868 and #971. But those are definitely interesting results.

One possible quick solution that we could implement is to add the “largeHeap=true” to the Corona app’s AndroidManifest.xml file as documented here…
http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap

We’ve been avoiding that setting since Google has warned against using it, but with no real explanation other than it may reduce the app’s performance and force Android to exit backgrounded apps to free up memory for the foreground app. Also, we’ve read that not all devices may honor that setting. But, this setting may be worth looking into at this point. [import]uid: 32256 topic_id: 29558 reply_id: 131989[/import]

@Joshua Just submitted a bug report. I was able to identify the specific order of loading things that causes the error on one of our devices, so I just sent you a short test case instead of our whole project. [import]uid: 135827 topic_id: 29558 reply_id: 132004[/import]

I tried a bunch of other random things with no success.

Looking at the logs both akao and I posted, I noticed something a little strange. It looks like memory is allocated twice on the heap for each sprite (and our crashes happen on the second attempt to allocate)? Not sure if that’s normal, but thought I’d point it out just in case.

Edit: Tried a couple more things

  1. Reverting to Corona version 900. Android 4.1 - Worked
  2. Reverting to Corona version 868. Android 4.1 - Worked
  3. Tested on the HTC Droid Incredible. Android 2.2 - Worked. Also notably, did not seem to allocate memory twice when loading sprites. [import]uid: 135827 topic_id: 29558 reply_id: 131902[/import]

Thanks for the quick response Josh. Yes, the Kindle Fire HD is definitely running out of memory, which is surprising given that it’s a newer device. But to your second point, I believe the crash is actually happening within Corona or the underlying OS.

To clarify, we actually had 2 print statements, around the code that I sent above. It actually looks something like this:

print ("Mark 1");  
foobar = sprite.newSpriteSheetFromData( hdFileName, coordinateData );  
print ("Mark 2");  

The first print shows up right before the dump posted above, and the second print statement never shows up. So, the crash is actually within the newSpriteSheetFromData() call. My guess is that somehow the try/retry that Corona is trying to do isn’t working for Kindle specifically. When we try the same code on NOOK and Nexus 7 devices, it appears that the try/retry does work. No error.

In terms of work around, our only workaround is to not use the HD 2048x2048 spritesheet. We already delay loading assets in our app. But this one spritesheet seem to bust Kindle. I suppose we can try breaking the sheet up into smaller chunks and lazy load each chunk, but that would create a tons of additional work… [import]uid: 41124 topic_id: 29558 reply_id: 131924[/import]

Just tried our app on on a Sony Tablet S (SGPT111), android 4.0.3 with the following results:

Corona Build 868:
Game loaded successfully

Corona build 971:
Crashed, out of memory followed by a segfault. It also crashes on other scenes with similarly sizes spritesheets.

Looking at the logs, one unusual detail is that in Build 971 it runs out of memory while using 19770K/39669K of heap. But in build 868 the app immediately starts out with a limit of 48647K heap memory and grows up to a max of 39866K/48647K on the offending sprite-sheet, then continues working just fine.

I opened up adb shell on this device and ran dumpsys meminfo on the Corona process and the data seems to add to theory that the device is allocating less max heap to apps built with newer versions of Corona.

Here’s the output I got:
https://gist.github.com/2e23fcaa183de2ca4648 [import]uid: 135827 topic_id: 29558 reply_id: 131984[/import]

Hmm… I’m getting the impression that the Kindle Fire HD has a lazy garbage collector, because a 64 MB maximum heap size “is” big enough to load 2048x2048 images. And you may be right about the [lua]sprite.newSpriteSheetFromData()[/lua] function causing the crash because it may not be handling the case where the image fails to load, unlike our other functions. I personally haven’t tested for this case myself with our newest sprite API.

Would you two mind sending us your Corona projects so that we can reproduce this issue for ourselves? You can do so by clicking the “Report a Bug” link at the top of this page. Make sure to mention this forum thread and my name so that our tech-support group knows to talk to me about it when they receive your bug report.

Oh and I hope I didn’t come across as difficult. Every once in a while we do get tech-support issues about out-of-memory errors, but they’re usually not Corona issues and are really because the app is attempting to load too many images; more than a low-end Android device is capable of storing in memory. But I’m always willing to be convinced otherwise. :slight_smile:

And in case you are interested, the reason why Corona is able to load your images without issues on a low-end Droid or Nook device is because Corona actually looks at the max heap size, calculates the memory needed to load the image, and automatically lowers the color quality and/or down-samples the image so that it can load it into memory. We really went well out of our way to make image loading as robust as possible. Especially on low-end devices, of which there are too many. So, I hope this gives you some confidence. It just looks we need to take care of this one last thing.
[import]uid: 32256 topic_id: 29558 reply_id: 131987[/import]

George,

In my experience, the max heap size is set by the device. It does not change when building your app against different Android API Levels, which is the only real difference between Corona build #868 and #971. But those are definitely interesting results.

One possible quick solution that we could implement is to add the “largeHeap=true” to the Corona app’s AndroidManifest.xml file as documented here…
http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap

We’ve been avoiding that setting since Google has warned against using it, but with no real explanation other than it may reduce the app’s performance and force Android to exit backgrounded apps to free up memory for the foreground app. Also, we’ve read that not all devices may honor that setting. But, this setting may be worth looking into at this point. [import]uid: 32256 topic_id: 29558 reply_id: 131989[/import]

@Joshua Just submitted a bug report. I was able to identify the specific order of loading things that causes the error on one of our devices, so I just sent you a short test case instead of our whole project. [import]uid: 135827 topic_id: 29558 reply_id: 132004[/import]

@Joshua - Want to see if you have had a chance to look into this issue? I can’t figure out from the release notes if this was one of the issues addressed in the newer releases? I believe we may be seeing the same issues on other Android devices (based on user feedback, but can’t be 100% sure).

Also, does switching to imagesheet or some other API fix this problem?

Sorry, we haven’t had a chance to send you our code since our overall code base is large, and this is a fairly entertwined part of our code-base. I’ll see if we can spend some more time on this in the coming days…

Thx!

[import]uid: 41124 topic_id: 29558 reply_id: 136036[/import]

akao,

We were able to test George’s app on a Sony Tablet and reproduce this problem. What we saw is that that the JVM was telling us that it had a max heap size of 48 MB, but it was only giving us up to 32 MB. Either the JVM is lying to us on only certain Android devices (because most devices don’t have this problem) or there is something that we’re not understanding here. In any case, our image loading code thinks it has enough heap memory to load an image when it really doesn’t.

George was able to work-around the problem by adding a “largeHeap=true” to his AndroidManifest.xml file, which he can do since he is using Corona Enterprise. I think that manifest setting is fine for large games, but it’s definitely not something we want to enable by default for all Corona Simulator builds. Perhaps as a quick solution we should make it an option in the “build.settings” file.

The ultimate solution on our end is to move image loading to the native C/C++ side on Android so that we would no longer be constrained by the JVM’s max heap size, which is pitifully small. Doing so would be a lot of work on our end and we’re not quite prepared to do that at the moment. We would have to add zip file support to Corona first in order to access the image files inside of the APK from C/C++, but hey, people want that feature too.

In any case, that’s our current thoughts on this matter.
So, as a quick solution, would you be okay with a “largeHeap” setting too?
[import]uid: 32256 topic_id: 29558 reply_id: 136039[/import]

@joshua - Thanks for the quick response as always!

Yes, I think a largeHeap size solution, (since it seems that’s a much easier solution on your end) would be a fine solution in the short term. I can let you know if we hear more user complaints. Also, I actually have a customer of mine who is willing to help do some testing, so I can send my code (with this fix) to him and have him try it out easily.

Do you need me to file a bug? Can this be done relatively quickly? I am surprised that George and I are the only ones who seem to be running into this issue…

BTW, this explanation makes sense, since I have been trying to reproduced the problem this morning with a test app that just loads lots of spritesheets, without success. It seems that the crash happens in the context of the app where we have other obects (audio, etc) that are being loaded into memory.
[import]uid: 41124 topic_id: 29558 reply_id: 136041[/import]

Okay… I’ll look into adding the “build.setting” option next week.
I won’t be back from the holidays until this coming Wednesday. Would you mind posting me a reminder on this forum thread then please? Because I’m afraid a bug report won’t reach me in time since most of our team will be out next week. Thanks! [import]uid: 32256 topic_id: 29558 reply_id: 136046[/import]

Thank you so much Joshua. I really appreciate the support!!
Will do so next Wednesday when you come back.

Have a Merry Christmas
[import]uid: 41124 topic_id: 29558 reply_id: 136047[/import]

A bump, in case you’ve forgotten this, Joshua. We’re having too many problems using Corona Enterprise to build for Android, so this feature is important to us as well, since our latest app does not start on a bunch of devices due to the same issue. [import]uid: 21746 topic_id: 29558 reply_id: 136378[/import]

Everyone,

We just finished adding the largeHeap option today. This change will be made available in daily build #994, tomorrow.

You can set up your app to use a large heap by adding the following to your “build.settings” file…
[lua]settings =
{
android =
{
largeHeap = true
}
}[/lua]

Please note that this is an Android 3.0 or higher setting. Android 2.x devices will still run your app, but will ignore this setting, which shouldn’t be an issue since they’ll likely have lower res displays compared to modern devices.

We’ve confirmed a few weeks ago that it raises the max heap size on a Sony Tablet S from 32 MB to 256 MB, allowing a Corona made app to load 2048x2048 image without any issues.

If you don’t mind, please let us know if this setting works-around the image loading issues that you have encountered. Thanks! [import]uid: 32256 topic_id: 29558 reply_id: 136404[/import]

@Joshua - Want to see if you have had a chance to look into this issue? I can’t figure out from the release notes if this was one of the issues addressed in the newer releases? I believe we may be seeing the same issues on other Android devices (based on user feedback, but can’t be 100% sure).

Also, does switching to imagesheet or some other API fix this problem?

Sorry, we haven’t had a chance to send you our code since our overall code base is large, and this is a fairly entertwined part of our code-base. I’ll see if we can spend some more time on this in the coming days…

Thx!

[import]uid: 41124 topic_id: 29558 reply_id: 136036[/import]

akao,

We were able to test George’s app on a Sony Tablet and reproduce this problem. What we saw is that that the JVM was telling us that it had a max heap size of 48 MB, but it was only giving us up to 32 MB. Either the JVM is lying to us on only certain Android devices (because most devices don’t have this problem) or there is something that we’re not understanding here. In any case, our image loading code thinks it has enough heap memory to load an image when it really doesn’t.

George was able to work-around the problem by adding a “largeHeap=true” to his AndroidManifest.xml file, which he can do since he is using Corona Enterprise. I think that manifest setting is fine for large games, but it’s definitely not something we want to enable by default for all Corona Simulator builds. Perhaps as a quick solution we should make it an option in the “build.settings” file.

The ultimate solution on our end is to move image loading to the native C/C++ side on Android so that we would no longer be constrained by the JVM’s max heap size, which is pitifully small. Doing so would be a lot of work on our end and we’re not quite prepared to do that at the moment. We would have to add zip file support to Corona first in order to access the image files inside of the APK from C/C++, but hey, people want that feature too.

In any case, that’s our current thoughts on this matter.
So, as a quick solution, would you be okay with a “largeHeap” setting too?
[import]uid: 32256 topic_id: 29558 reply_id: 136039[/import]

@joshua - Thanks for the quick response as always!

Yes, I think a largeHeap size solution, (since it seems that’s a much easier solution on your end) would be a fine solution in the short term. I can let you know if we hear more user complaints. Also, I actually have a customer of mine who is willing to help do some testing, so I can send my code (with this fix) to him and have him try it out easily.

Do you need me to file a bug? Can this be done relatively quickly? I am surprised that George and I are the only ones who seem to be running into this issue…

BTW, this explanation makes sense, since I have been trying to reproduced the problem this morning with a test app that just loads lots of spritesheets, without success. It seems that the crash happens in the context of the app where we have other obects (audio, etc) that are being loaded into memory.
[import]uid: 41124 topic_id: 29558 reply_id: 136041[/import]