i am making an application and on the start of application i want to display a picture but i get this out of memory exception. i used a lot of shared Preferences in the code that is not yet executed. so this rises 2 questions -
is memory for shared Preferences allocated at the beginning itself ?
and is the memory for shared Preferences allocated in the apps heap memory ?
should i clear the shared preferences and use database instead . will that solve the problem ?
Android hardware must at least support 2048x2048.
For OpenGL I used:
int[] maxSize = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
For Nexus 4 it equals to 4096
For Sansung 2 it equals to 4096
You can calculate [(Height in pixels) x (length in pixels) x (bit depth)] / 8 / 1024 = image size in kilobytes (KB)
So be sure that you have proper image size.
Hope it will help,
Related
I'm running into out of memory exceptions in device log generated by GPU when trying to load heavy graphics scene using VBO on Android.
20:53:48.640 app W/Adreno-GSL: <sharedmem_gpumem_alloc_id:2255>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
20:53:48.642 app E/Adreno-GSL: <gsl_memory_alloc_pure:1971>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
Raw binary data size i'm trying to supply is less than half of available amount of RAM. After doing some research, i found that after each glBufferData(..) call the amount of free memory decreases 2 times the size of data supplied (tried on different devices, same result). Here is my setup:
logMem("before buff creation");
ByteBuffer dummyBuff = ByteBuffer.allocateDirect(1024 * 1024 * 16).order(ByteOrder.nativeOrder());
byte[] some = new byte[1024];
for (int i = 0; i < dummyBuff.capacity(); i+= some.length) {
dummyBuff.put(some);
}
dummyBuff.rewind();
logMem("buff data created");
int[] bufferHandles = new int[1];
GLES20.glGenBuffers(1, bufferHandles, 0);
int bufferHandle = bufferHandles[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, dummyBuff.capacity(), dummyBuff, GLES20.GL_STATIC_DRAW);
logMem("buff data supplied");
Amount of memory left is logged with
manager = (ActivityManager) getSystemService( Activity.ACTIVITY_SERVICE );
info = new ActivityManager.MemoryInfo();
...
manager.getMemoryInfo(info);
Log.v("mem", tag + ", mem " + info.availMem/1024/1024);
Here is what i am getting in the log
20:13:34.243 V/mem: before buff creation, mem 1381
20:13:34.466 V/mem: buff data created, mem 1366
20:13:34.500 V/mem: buff data supplied, mem 1334
I also tried a combination of
GLES20.glBufferData(.., dummyBuf.capacity(), null, ..);
GLES20.glBufferSubData(.., 0, dummyBuf.capacity(), dummyBuf);
In this case after first line execution i was getting a loss of 1x buffer size, as expected, but with the second, another 1x buffer size of memory was gone.
I tried it on 2 different devices utilizing different GPUs (Adreno, Mali) and was getting same behavior. So, my question is: am i missing something, or is this an expected behavior? Is there any way to decrease this RAM impact when supplying data to VBO?
Are you remembering to free the copy of the buffer you allocated?
In OpenGL ES all GPU server-side resources (textures, buffers, programs, etc) are copied into memory owned by the driver stack. Drivers can't just keep pointers to the buffers allocated by the application.
Once you have uploaded the data you can safely delete the application-side copy; it's not needed any more.
I am facing difficulties to get updated available heap size of application after removing some of the large objects.
My requirement is to free the memory once user reach the specific level of heap size. e.g I am using Samsung Tab3 which has 64 Mb heap size for an application.
Application should't go out of memory while viewing images, hence i have restricted 55 MB as max limit for heap size to grow. I am checking available heap size before view image. If the heap size is greater than 55 MB then I remove the some of the images which are recently viewed, so i can get enough memory to load image.
But the problem is that the, after removing images objects, I got the last increased heap size, which is always greater than 55 MB. I also called gc after remove each image, but doesn't affect.
I want the decreased heap size after removing image object.
if heap has reached 55 MB then on each removal heap should decrease, how to get decreased heap size?
I am using following codes to get available heap size.
/**
* This method is used to get currently allocated heap size to application.
*/
public static int getAllocatedHeapSize()
{
DecimalFormat df = new DecimalFormat();
int size = new Double(Runtime.getRuntime().totalMemory()/1048576).intValue();
Log.d("heap", "debug.memory: allocated: " + size + "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory()/1048576))+ "MB (" + df.format(new Double(Runtime.getRuntime().freeMemory()/1048576)) +"MB free)");
return size;
}
/**
* Check whether free memory is available to store new attachment page
* #return true if available else false
*/
public static boolean isFreeMemoryAvailable()
{
int allocatedHeapSize = getAllocatedHeapSize();
if (allocatedHeapSize > ) {
return false;
}
return true;
}
isFreeMemoryAvailable() method goes in infinite because its not getting updated heap size.
Give me a solution as soon as possible.
Runtime.totalMemory() is not related to how much of the heap that is actually used when called. It returns the actual size of the heap. From the documentation:
Returns the number of bytes taken by the heap at its current size.
Removing objects does not necessarily change the heap size.
You could get the actual usage of the heap by doing:
Runtime.totalMemory() - Runtime.freeMemory();
That said, maybe you should look at storing your images in a android.util.LruCache or something instead of doing this management yourself.
There are several aspects to this question:
1) You might get more reliable and detailed statistics using java management beans, e.g., http://docs.oracle.com/javase/7/docs/api/java/lang/management/MemoryMXBean.html among other (MemoryMXBean, MemoryPoolMXBean, GarbageCollectorMXBean)
2) You cannot reduce your heap size from within the java application, you can only reduce your usage of the heap.
3) You might consider the usage of Soft References http://docs.oracle.com/javase/7/docs/api/java/lang/ref/SoftReference.html. This class enables you to keep references as long as the space is not needed otherwise, and collect it only when absolutely necessary. This way you can limit your heap size, and use soft references to keep data as long as possible but do not impede the GC collecting it if necessary.
I have an android app, this application connect to server to download images, but this images has more than one copy, first copy 1600 * 1080 pixel and the second is 800 * 540 ...
so the device should send tag to server to download the good images for this device
I used many ways to check the device memory or density but the results was not clear enough to make a decision, here some code I used:
float density = getResources().getDisplayMetrics().density;
long mem = Runtime.getRuntime().freeMemory();
long heap = Debug.getNativeHeapAllocatedSize();
the results was for 3 devices like this:
samsumg tab 10 inch = 1.0 , 745464 , 3249552 byte
china tab 7 inch = 1.0 , 559944 , 2789016 byte
htc moble 3.4 inch = 1.5 , 1760904 , 8942736 byte
as the result showed the htc is the better but it was not because I can't view the highest resolution on it, but on the other devices it was very good
the error msg:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=7687KB, Allocated=3356KB, Bitmap Size=25092KB)
Any help in this issue ?
Your decision should depend on two factors:
Screen density.
Screen Size.
In your case you had received hdpi drawables on htc, but it's small device, so it's not required to show large image with more details on small device.
for more information for loading large bitmaps efficiently:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
On my xperia ray app fails on start when memsize > 50mb (can't alloc so mush). But when memsize = 50mb, app can work around 5 mins, and then fails with message from marmalade, that not enough memory. So how can i find out how mush memory my app needs in peak?
In my .icf file:
MemSize=200000000
#if resolution < 1080x1920
{ [s3e]DispAreaQ < 2073600 }
MemSize=150000000
#if resolution < 640x854
{ [s3e]DispAreaQ < 546560 }
MemSize=52428800
{}
You need to turn on simulator's view matrix option and look under graphics's memory. Check what's the max size it's using. Although simulator's memory usage is different from device's usage, but it'll give you an idea about what memory size is required.
Edit:-
If you need to have different Memsize for debugging you can use MemSizeDebug too, along with MemSize.
I want to acquirećAndroid Device VRAM size.
Is there a method for acquisition from the program?
Let's do some calculation using Nexus One:
Screen resolution is 480x800. So minimum required video memory size would be:
400 * 800 * 4 bytes = 1536000 bytes
Assuming that driver may (and normally should) use several buffers, we should also expect values like:
1536000 * 2 bytes = 3072000 bytes
1536000 * 3 bytes = 4608000 bytes
etc...
It would be weird to have values that are not multiple of 1536000 (or W x H x 4 in general).
After some searches on Android internals I've found this documentation :
...Android makes two requirements of the driver: a linear address space of mappable memory that it can write to directly...accessing the driver by calling open on /dev/fb0...
So I tried and take size of /dev/graphics/fb0 file (on my device there is no /dev/fb0).
But a direct approach doesn't work:
File file = new File("/dev/graphics/fb0");
file.length(); // ==0, doesn't work, no read access
Using next trick you can get actual size of fb0:
>adb pull /dev/graphics/fb0
1659 KB/s (4608000 bytes in 2.712s)
Video memory is ~4mb (Nexus One). Let's check if this is multiple of Nexus screen size:
4608000/1536000 = 3
It looks like a right value. And we also can say that driver uses three screen buffers.
So, as a conclusion, you can detect video memory size using adb, but you can't use this approach from your android application in runtime due to file access restrictions.
You typically do not have a dedicated "VRAM" on mobile devices. At least you don't have it with PowerVR architectures (wich totally dominate the market with their MBX and SGX cores).
That is, the OpenGL driver allocates normal RAM until you run out of it, and the more you allocate the less you have left for your application.
The Android/OpenGL APIs don't offer explicit methods to read the VRAM size from a given device.
Poor man solution:
You could try to infer the VRAM size in an empiric way adding 1MB texture until you get an out of memory error from gl.glGetError().
From your "dmesg" output u can read off the VRAM, so for my Tablet:
> [ 0.000000] Machine: TDM3730 [ 0.000000] Reserving 12582912
> bytes SDRAM for VRAM
>
> 7>[ 3.929962] VRAM: checking region 9f400000 3072
> <4>[ 3.929992] Failed. Allocating 4194304 bytes for fb 0
> <7>[ 3.935333] VRAM: alloc mem type 0 size 4194304 paddr dec2bd4c
> <7>[ 3.935485] VRAM: checking region 9f400000 3072
> <7>[ 3.935485] VRAM: found 9f400000, end a0000000
> <6>[ 3.936584] android_usb gadget: high speed config #1: android
> <4>[ 3.960113] allocating 4194304 bytes for fb 1
or details at:
http://pastebin.com/jQSXQqHh
Is simple just count how many Mb ram that from usable to real capacity of the ram, example for my lenovo a369i has 512 RAM Module, but in setting app only showing 471 Mb usable so the 41Mb left is reserved for the GPU, so the conclusion is my a369i has 41Mb vram
This method is based from shared graphics memory (wiki)
I suspect that android.os.StatFs is what you're looking for:
http://developer.android.com/reference/android/os/StatFs.html