ixx
ixx

Reputation: 32269

Enormous memory (native heap) increase setting a layout

I get an increase of native heap usage of 6 MB when I'm expecting an increase of about 0.1 MB

How I came to these numbers:

Log.d("test", "before setting layout");
showMemoryStats();

setContentView(R.layout.my_layout);

Log.d("test", "after setting layout");
showMemoryStats();

Where showMemoryStats is:

public static void showMemoryStats() {
    Log.i("test", "----------------------------------------------------------------------------------------------------------------------------");
    Log.i("test", "showing memory stats in xx");
    double nativeUsage = Debug.getNativeHeapAllocatedSize(); 
    Log.i("test", "nativeUsage: " + nativeUsage);
    //current heap size 
    double heapSize =  Runtime.getRuntime().totalMemory();
    Log.i("test", "heapSize: " + heapSize);
    //amount available in heap 
    double heapRemaining = Runtime.getRuntime().freeMemory();   
    Log.i("test", "heapRemaining: " + heapRemaining);
    double memoryAvailable = Runtime.getRuntime().maxMemory() - (heapSize - heapRemaining) - nativeUsage;
    Log.i("test", "memoryAvailable: " + memoryAvailable);
    Log.i("test", "----------------------------------------------------------------------------------------------------------------------------");
}

The output:

07-03 16:50:40.127: D/test(18647): before setting layout

07-03 16:50:40.127: I/test(18647): ----------------------------------------------------------------------------------------------------------------------------

07-03 16:50:40.127: I/test(18647): showing memory stats in xx

07-03 16:50:40.127: I/test(18647): nativeUsage: 5706008.0

07-03 16:50:40.127: I/test(18647): heapSize: 4905968.0

07-03 16:50:40.127: I/test(18647): heapRemaining: 1815456.0

07-03 16:50:40.127: I/test(18647): memoryAvailable: 2.4757912E7

07-03 16:50:40.127: I/test(18647): ----------------------------------------------------------------------------------------------------------------------------

07-03 16:50:40.348: D/dalvikvm(18647): GC_EXTERNAL_ALLOC freed 100K, 49% free 2924K/5639K, external 0K/0K, paused 45ms

07-03 16:50:40.518: D/dalvikvm(18647): GC_EXTERNAL_ALLOC freed 9K, 49% free 2917K/5639K, external 2700K/3371K, paused 51ms

07-03 16:50:40.638: D/dalvikvm(18647): GC_EXTERNAL_ALLOC freed 4K, 49% free 2928K/5639K, external 3952K/4356K, paused 51ms

07-03 16:50:40.698: D/dalvikvm(18647): GC_EXTERNAL_ALLOC freed 2K, 48% free 2933K/5639K, external 5963K/6027K, paused 24ms

07-03 16:50:40.718: D/test(18647): after setting layout

07-03 16:50:40.718: I/test(18647): ----------------------------------------------------------------------------------------------------------------------------

07-03 16:50:40.718: I/test(18647): showing memory stats in xx

07-03 16:50:40.718: I/test(18647): nativeUsage: 1.2101904E7

07-03 16:50:40.718: I/test(18647): heapSize: 4734944.0

07-03 16:50:40.718: I/test(18647): heapRemaining: 1716432.0

07-03 16:50:40.718: I/test(18647): memoryAvailable: 1.8434016E7

07-03 16:50:40.718: I/test(18647): ----------------------------------------------------------------------------------------------------------------------------

The maths:

12101856 bytes - 5703424 bytes = 6398432 bytes = 6.10202 mb

I went though my layout file and added the size of all the drawables used, and came to a total size of 124 kb -> 0.121094 mb

So what on earth is causing the native heap to increase 6 mb?

I can put the layout file, if somebody ask for it, don't know if it makes sense... just a bunch of layouts with ids and drawables, and as said I already checked the drawables for the size.

Thanks a lot in advance...

Edit: This was the solution, in my case - in order to summarize the responses and comments: I was storing the images in the folder "drawable" and using a hdpi device. Solution: put the images in folder drawable-hdpi. Reason: The system was stretching my images from "drawable" in order to match hdpi resolution, although they were already in hdpi resolution. This made them occupy more than 2x of memory than they should.

Upvotes: 3

Views: 1092

Answers (2)

IAmGroot
IAmGroot

Reputation: 13855

Well, Bitmaps take a huge amount of space up.

Each pixel requires 4 Bytes!

So a 1M pixel Image is 4MB!!! I assume you are using many smaller images, but they soon add up.

One way around this is to load the bitmaps at a lower resolution (in most cases you wont notice any difference as they are not being displayed at max res anyway). Look into BitmapFactory.Options.inSampleSize for this.

As quoted from android

Bitmaps take up a lot of memory, especially for rich images like photographs. For example, the camera on the Galaxy Nexus takes photos up to 2592x1936 pixels (5 megapixels). If the bitmap configuration used is ARGB_8888 (the default from the Android 2.3 onward) then loading this image into memory takes about 19MB of memory (2592*1936*4 bytes), immediately exhausting the per-app limit on some devices.

Here is a great link to explain it better .

Upvotes: 1

Dude
Dude

Reputation: 662

The Problem is that when android has to draw your drawables on the screen, they are much bigger than when they are in your res folder. If you have for example a PNG that is 100 Kb, then this is the compressed size. When android draws the PNG on the screen, it blows it up to the normal size which is per default (4 Bytes) * (height in pixel) * (width in pixel). This is because it stores 4 byte of color information for every pixel that your image has. This means if your image is for example 800 x 600 pixel that the resulting bitmap that android generates is 800x600x4 bytes = 1920000 bytes = something near 2 Mb.

If you want to get around this problem you have to use smaller images.

Upvotes: 1

Related Questions