Image loading fails on Android, is there a max memory limit?

We're running into an issue where I'm trying to launch the game on the Ouya, but the debugging in Eclipse is showing us that it's suddenly stops loading images in this last batch of folders. It's not some FileNotFound Exception or any permissions, the Ouya just suddenly stops working when it's trying to load these last few images.

Our Assets folder is a total size of 115MB in images so I think that's ok unless someone could tell otherwise.

The LogCat is showing me that the garbage collector is being called a lot, freeing around 1100KB per run, but it mostly says that there is 63% of free 11868K/31431K.

I've run it a bunch of times, restarted my computer and the Ouya, uninstalled the app and reinstalled it, but this problem continues to persist. I thought perhaps there was something wrong with the images, but when I changed the order of the images loaded, those images passed, and now it's a different set of images it crashes on that it use to be able to load.

Has anyone come across this problem or have any suggestions? The images are PNG format.

Comments

  • MagnesusMagnesus Posts: 304Member
    edited January 2013
    How are you loading images? Can you show that part of the code? 115MB is a lot considering PNG is compressed. A LogCat part when the images stop loading would be useful too. Are you using any framework or OpenGL?
    Post edited by Magnesus on

  • mjoynermjoyner Posts: 168Member
    Lots of GC messages should also be taken as a serious warning about memory allocation/reallocation issues.
  • vinfangvinfang Posts: 8Member
    edited January 2013
    Unfortunately, when the application stops working, the LogCat doesn't show anything peculiar, except for the regular GC calls. It just stops without giving any error or exception which is what we find odd. It doesn't say out of memory errors either.

    Texture nTexture = new Texture(Gdx.files.internal(pPath));

    We're using the gdxlib library where this Texture class is provided from. We just specify the file of the path of the image to this class, and use one of the Gdx utilities to convert the path to a file handle that this Texture class uses.


    Here's their Java api doc. Right now I'm trying to use this GC_CONCURRENT showing up in LogCat like mad as some kind of clue. Can GC be called this frequently when loading images? I'm seeing that there's about 21255KB of memory allocated for us but we're only using about 55% right now.

    Also, can anyone detail or reference a website on how to troubleshoot memory or garbage collection issues? I'm trying to figure out where or what in the code is leading to the GC being called this often.
    Post edited by vinfang on
  • MagnesusMagnesus Posts: 304Member
    edited January 2013
    So you are using libGDX. You texture loading code looks normal. I'm afraid you might load too much textures then... Do you need to have all of them at once? Maybe you could dispose of some and load some new when levels begin etc. to conserve some memory? The memory used by textures is not visible in GC information AFAIK. The lack of LogCat error - are you sure about it? If it's caused by NDK it might be one line with error number not even associated to your app.
    There shouldn't be much GC calls when you are only loading things - it's called mostly when you dispose of a lot of objects. Maybe lack of memory triggers it too...

    PS. You are loading the textures in the constructor?
    PS.2. You might consider posting this problem to badlogic (libgdx) forum too.
    Post edited by Magnesus on

  • badlogicbadlogic Posts: 23Member
    115MB compressed PNGs is way to much to load all at once. Create a simple ApplicationListener that just loads all your assets and see if the problem persists. If it does, reduce the amount of loaded assets until the app isn't crashing anymore. If that works, your only option is to not load all assets at once but on a need basis.
  • vinfangvinfang Posts: 8Member
    edited January 2013
    Yes we found out through more testing that although no errors are being given, it's just too much for the Android app running. I've cut out one load of images which happened to be 95 MBs and the game worked and loaded fine, but of course then it would probably crash when it tries to reference something that doesn't exist. I don't know what the Android limit is for apps and their resources to load while it's running. Does anyone have a reference?

    Also I wanted to add that the reason the images are so large is because they're high def. Apparently this is not a good idea now?
    Post edited by vinfang on
  • MagnesusMagnesus Posts: 304Member
    edited January 2013
    You have approximately 512MB in total on OUYA, but it's better to assume 256MB for GPU. Textures take much more memory than PNG files.
    Post edited by Magnesus on

  • badlogicbadlogic Posts: 23Member
    It is highly unlikely that you need all those images at once. Your only option is to only load what you need a specific time, e.g. within a menu, only load the menu assets, within a stage, only load the stage assets.
  • vinfangvinfang Posts: 8Member
    We're going to try out the dynamic loading, but unfortunately one of the rooms our game takes place in requires the use of the boss sprites which is over 90 MB, so we going to have to figure out a way to reduce the size and make it less complex. The rest of the game is around 15MB compressed.


    Thanks for the info guys, it helps explain a lot of the issues we're seeing and I didn't even realize that the Android takes a lot of the 1GB RAM space when it's trying to run an app.
  • MagnesusMagnesus Posts: 304Member
    Maybe compressed textures would help? I don't know anything about them apart from that they exist though. :) Tegra even has its own format.

  • badlogicbadlogic Posts: 23Member
    we currently only support etc1 which does not have an alpha channel. guess i could implement the other formats :)
  • DreamwriterDreamwriter Posts: 768Member
    Tegra uses DXT natively, I think if you use that then the texture can remain compressed even in video RAM
  • jbanesjbanes Posts: 45Member
    I'm probably going to software engineering hell for telling you about this, but there is a manifest option for large heap:


    On my system (MK808 w/1GB RAM), the system reports that it will allocate my program up to 384MB of RAM. I haven't tested it nearly that high, but it is an option if you just can't get the textures reduced. You're on your own for pumping that many texels...
  • badlogicbadlogic Posts: 23Member
    That's just for the Dalvik == managed Java heap. Textures go on the native heap (in case it's a shared memory architecture like on most mobiles) or on dedicated GPU Ram. That option won't help. Texture compression is the only option i can offer.
  • jbanesjbanes Posts: 45Member
    edited January 2013
    Duh, I knew that. Don't know why it wasn't clicking. Thanks for the thwack on the head. :) Edit: Sorry, I just realized there's one point that's confusing me. Why all the garbage collection? Shouldn't each Bitmap get loaded, copied to native heap, then recycled for the next image? If he's seeing a lot of GC, it seems like he must be doing something wrong in the load procedure?
    Post edited by jbanes on
  • badlogicbadlogic Posts: 23Member
    byte array allocation when loading an image. that's done on the java heap, passed to C for decoding, then uploaded to the GPU. Only performant way to be able to handle InputStreams. Could use a shared scratch buffer but that would take away memory and it's size would be dependent on the application. He's basically allocating 90mb of Java heap, not at once, but over the entire loading time.
  • badlogicbadlogic Posts: 23Member
    Actually, it could be solved differently via some native heap memory and a tiny static scratch buffer. i'll put that on my todo list, thanks for pointing it out!
  • jbanesjbanes Posts: 45Member
    And thank you for putting up with my questions. I probably sound like a bloody novice, but this stuff is really helping clarify my understanding of the Android platform. :)
Sign In or Register to comment.