0

I am making an app that involves a lot of animation.

For example: I got a group of png files(50+) and iterate them with the frame rate of 15fps, to make it looks like an animation.
I have many groups of image files like that. image size: 480x800, with alpha.

my app works basically okay, while I found a lot of GC_FOR_ALLOC in the logcat while playing animation.

my question is that with so many GC_FOR_ALLOC, can I just ignore them, or figured someway to eliminate them? my app also has an minor problem, not sure if related with GC, on some older android devices, the frame rate can not get to even 10fps.

I tried to recycle the bitmap, but it seems only mark that item is available for GC.

I load image this way:

        BitmapFactory.Options localOptions = new BitmapFactory.Options();
    localOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
    try {
        return BitmapFactory.decodeStream(context.getAssets().open(fileName), null, localOptions);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;

after load the image, I draw them on SurfaceView, like this:

 canvas.drawBitmap(BgImage,rectBG2, rectScreen2, null);

for every frame, I need to draw about 3 images(3 layers). not sure if that has anything to do with GC.

below is an example of those GCs:

D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17653K/32583K, paused 29ms, total 29ms
E/ttt     ( 4993):    66
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17653K/32583K, paused 25ms, total 25ms
E/ttt     ( 4993):    64
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1500K, 46% free 17654K/32583K, paused 25ms, total 25ms
E/ttt     ( 4993):    64
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 26ms, total 26ms
E/ttt     ( 4993):    66
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 37ms, total 37ms
E/ttt     ( 4993):    83
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1500K, 46% free 17654K/32583K, paused 37ms, total 38ms
E/ttt     ( 4993):    68
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 25ms, total 26ms
E/ttt     ( 4993):    53
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1500K, 46% free 17654K/32583K, paused 25ms, total 26ms
E/ttt     ( 4993):    62
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 27ms, total 27ms
E/ttt     ( 4993):    67
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 27ms, total 27ms
E/ttt     ( 4993):    67
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1500K, 46% free 17654K/32583K, paused 26ms, total 26ms
E/ttt     ( 4993):    66
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1501K, 46% free 17654K/32583K, paused 27ms, total 27ms
E/ttt     ( 4993):    66
D/dalvikvm( 4993): GC_FOR_ALLOC freed 1500K, 46% free 17654K/32583K, paused 26ms, total 26ms
E/ttt     ( 4993):    65

currently I am trying a way to load bitmap from JNI, like game engine did, not sure if this is the right way to do it.

springrider
  • 470
  • 1
  • 6
  • 19

1 Answers1

2

While your app should run fine with those, I would say your best bet is to look into getting rid of them. Remember that this means your app is having to constantly free resources, which is time-consuming for your app (when it's running that much), and also bad from a memory management perspective. You can see a bit more about this here: https://stackoverflow.com/a/11312145/3342157 While you may not have any issues now, it could potentially cause major slowdowns later (if it isn't already).

As for how to get rid of them, remember that you should only have to reload the image if you are changing it. If you aren't, I would say to not reload it each frame. If you have several images it will swap between and can afford to use the memory (not sure on the image sizes), load them all at the beginning, and then hold on to them for rendering later. I see that you are specifically talking about animation, and my recommendation would be to create a sprite sheet to prevent having to load each individual PNG image.

Community
  • 1
  • 1
GEMISIS
  • 434
  • 3
  • 11
  • thanks for the help. it's useful, as for the image size, it's 480x800 each. I can barely load 2-3 of them in the same time, load more would cause OOM... – springrider Jul 16 '14 at 03:49
  • I recommend you loading only 1 at a time (imagine what happens on larger screens, where you would load 1280*800 images) – Phantômaxx Jul 16 '14 at 07:39
  • I guess so, but then we back to the GC problem. since I can only load 1 image every time, also because of the size of the image, using sprite sheet is not practical. so there is no way to solve it? – springrider Jul 16 '14 at 09:32
  • 1
    Game devs have been dealing with problems like this for basically ever. :-) Depending on your goals, you can load smaller images and scale them, compress them in a way that allows them to uncompress quickly (e.g. RGB565 vs. RGB888, delta compression, RLE, ...), or find some other way to "cheat". The GC is reporting 1.5MB per GC, which is 480*800*4... do you need the alpha channel? At 15fps you've got some time to do work on the CPU. – fadden Jul 16 '14 at 14:29
  • I would also look into multithreading for loading each image (Specifically async tasks). This could potentially done at a certain point before you need the image to help offset it a bit, but yeah, with those size images that's a bit tricky haha – GEMISIS Jul 17 '14 at 01:29
  • yep, alpha channel is necessary, I got 3 layers, need alpha to make sure upper layer not override lower layer completely. I am currently trying to load bitmap through JNI, so I can manage memory by myself, is that how game devs deal with it? – springrider Jul 17 '14 at 01:51