Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heap not expanding on Genymotion emulator

While resizing large bitmaps for faster image upload to a server I occasionally ran into OutOfMemoryErrors. To prevent this I calculate the required amount of memory and check if it exceeds Runtime.getRuntime().maxMemory() before trying to scale an image.

However, I still run into OOM errors even though the image should fit on the heap easily.

The emulated device (Galaxy SII API 16) gives me a max memory of 67108864 bytes using the above method.

In the following snippet, the heap size is 43975K and only < 15K of that memory is in use. For my ~31K allocation the heap should grow automatically to about 45K which is still not even close to the maximum size of 64 MiB. But as you can see, instead of expanding the heap, the dalvik vm runs out of memory.

10-13 20:35:57.223: D/dalvikvm(1201): GC_FOR_ALLOC freed 505K, 67% free 14692K/43975K, paused 31ms, total 31ms
10-13 20:35:57.223: I/dalvikvm-heap(1201): Forcing collection of SoftReferences for 31961100-byte allocation
10-13 20:35:57.251: D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused 29ms, total 29ms
10-13 20:35:57.251: E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation.

I wonder if this can happen on a real device too or if this could be a genymotion bug.

Is the heap guaranteed to expand up to maxMemory()? The JavaDoc for Runtime.getRuntime().freeMemory() says it "may" expand, whatever that means.

I just need a realiable way to calculate the amount of memory I can use, this is how I did it, please correct me if I'm wrong:

long maxMemory = Runtime.getRuntime().maxMemory();
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long availableMemory = maxMemory - usedMemory;

This call causes the OutOfMemoryError:

// outOptions has an appropriate inSampleSize
BitmapFactory.decodeStream(inputStream, null, outOptions);
like image 629
wkarl Avatar asked Oct 13 '14 21:10

wkarl


3 Answers

Out of memory on a 31961100-byte allocation

Your bitmap is 32M. VM can't allocate 32M linear space to store bitmap. Heap is fragmented, so even if your heap has 32M free space it is not always possible to allocate such linear space. You can try free up as much memory as you can and call GC before decoding stream.

Try to decode your bitmap in more effective way. Or process image in parts. If you tell us why you need this image, we can tell you how to handle it.

like image 68
Leonidos Avatar answered Nov 19 '22 20:11

Leonidos


You have a 42MB heap , out of which 14MB is already used, 67% (28M) is free/available

    D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused ...
    E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation.

You are trying to allocate ~31M (not 31K) , which is greater than 28M that is available, resulting in OOM.

For details on interpreting dalvikvm memory allocation log message take a look at debugging memory

There is lot of shared memory usage going on in android, to properly calculate per process memory usage refer this SO question

Android best practices on efficient bitmap memory management may be of help

like image 26
ashoke Avatar answered Nov 19 '22 21:11

ashoke


One thing you might try to tweak is build.props file of the ROM.

On Genymotion emulator you can try executing the following via root shell:

cat /system/build.prop | grep dalvik 

and it would display the line with dalvik settings:

dalvik.vm.heapsize=256m
dalvik.vm.lockprof.threshold=500
dalvik.vm.stack-trace-file=/data/anr/traces.txt

And maxmemory is also being reported as 268435456 bytes on the emulator I experimented with.

So, you may try playing with this setting. Also, ensure that the memory allocated in VirtualBox's settings is compatible with these values.

like image 1
S.D. Avatar answered Nov 19 '22 20:11

S.D.