1

On android.com they say, that if you're working in Java, the maximum memory you can use is 16 MB. At least that's the one the devices are supposed to support. If you have an older phone, you'll notice that you can't get more, you get an OutOfMemoryError instead. Not if you're doing the same thing using the NDK. In on of my applications I am trying to get 50MB and more, and so far Android was fine with that.

I havn't found anything related to that on android.com.

Is there any limit like in Java, too?

If yes: what's the limit?

If no: What is a good value for that?

Problem is, that I have to build my code depending on that size.

[Edit:] I tried what Seva Alekseyev were suggesting.

     root@android:/ # ulimit -a
     ulimit -a
     time(cpu-seconds)    unlimited
     file(blocks)         unlimited
     coredump(blocks)     0
     data(KiB)            unlimited
     stack(KiB)           8192
     lockedmem(KiB)       64
     nofiles(descriptors) 1024
     processes            7806
     flocks               unlimited
     sigpending           7806
     msgqueue(bytes)      819200
     maxnice              40
     maxrtprio            0
     resident-set(KiB)    unlimited
     address-space(KiB)   unlimited
     root@android:/ # ulimit -v
     ulimit -v
     unlimited
     root@android:/ #

The memory I am requesting (by using "alloc" or "new") is virtual memory (ulimit -v). So there's no chance to figure out how much I can gain?!

andre
  • 1,618
  • 2
  • 19
  • 38
  • 1
    there is no hard limit for java / ndk, the 16mb is more like the amount you can expect to have. You can get as much as there is left in general, but 50mb is almost guaranteed to fail on old devices with ram < 200mb – zapl Nov 05 '12 at 15:15
  • On our HTC Legend, it was impossible to get more than 16 MB in Java. But we were able to get >16 MB (in our case it was 50 MB) in the C/C++ part on the same device. – andre Nov 05 '12 at 15:33
  • 1
    The native subsystem is subject to kernel-level restrictions on memory use. Look up the `ulimit` shell command, and play with it. Android being what it is, there's no guarantee you won't ever encounter a device where the limits are ridiculously low. – Seva Alekseyev Nov 05 '12 at 15:46

1 Answers1

2

You're subject to three types of memory limits:

1) Artificial limits put in place to keep the system responsive when multitasking -- the VM heap limitation is the main example of this. ulimit is a potential mechanism for a the OS to provide further limitations on you, but I have not seen it being used restrictively on Android devices.

2) Physical limits based on available real memory. You should have a baseline device you're developing/testing on, and should be pretty aggressive in assume other processes (background services, other apps) need memory too. Also remember that memory in use by the OS varies with OS version (and will tend to increase over time). Stock Android doesn't swap, so if you go too far you're dead. One potential scenario is a Nexus One (512MB RAM) with an audio player and the phone app going in the background, and a "balloon" service eating another 100MB physical memory to give some leeway; in this configuration you'll still find more than 100MB available.

3) Virtual memory limits based on address space. Stock android allows overcommitment of memory, so it won't blink if you ask for a 1GB virtual allocation (via mmap, etc) on a device with 512MB of RAM, and this is often a very useful thing to do. However, when you then touch the memory, it needs to be brought into physical memory. If there are read-only pages in physical memory they can be ejected, but soon enough you're going to run out, and without swap -- dead. (The combination and overcommit and no swap leads directly to process death in out-of-memory situations, rather than recoverable errors like malloc returning null).

Finally, it's worth noting that whether calloc/malloc/new require physical allocation is allocator-dependent, but it's safer to assume yes, especially for allocations less than a large number of pages. So: If you're dealing with < 100 MB of standard, well behaved allocations, you're probably in the clear -- but test! If you're dealing with large amounts of data that you'd like memory mapped, mmap is your friend, when used carefully, and is your best friend when used with PROT_READ only. And if you're dealing with > 100 MB of physical memory allocations, expect to run quite nicely on modern devices, but you'll have to define a baseline carefully and test, test, test, since detecting out-of-memory situations on the fly is not generally possible.

One more note: APP_CMD_LOW_MEMORY exists, and is a great place to purge caches, but there's no guarantee it's called in time to save your life. It doesn't change the overall picture at all.

addaon
  • 1,097
  • 9
  • 25