The Memory Benefits of 64-bit + How it Works

Oculus Developer Blog
Posted by Gabor Szauer
December 19, 2019

As Oculus Quest APKs must now be ARM64 compatible, we’ve requested that Oculus Developer Relations Engineer and published author, Gabor Szauer give us a breakdown of the benefits that come with 64-bit over 32-bit applications. In this overview he not only provides the reasoning to use ARM64, but also outlines an example build for added context.

This post explores the memory related benefits of switching to a 64-bit build. While you don’t actually get any more physical memory with 64-bit, this change will help eliminate memory pressure and make your application more stable. Let’s explore why that is, starting with the relationship between physical and virtual memory in Android.

The Android OS gives every application its own view of memory, this is what we refer to as virtual memory. The virtual view of memory is as large as the maximum addressable space. For a 32-bit application, this happens to be 4GiB the amount of physical memory does not change this fact.

On Quest, memory is not paged to disk. This means the physical memory available is used to back all of the virtual memory for all applications currently running. This physical memory is constant, it’s not going to change by switching to a 64-bit build. What will change is the size of the virtual memory address space.

Next, let’s talk about shared code. Android loads shared libraries once, then links them into the virtual address space of any application that uses the shared library. The Quest vision system for example is resident in memory once, but it’s mapped into the virtual address space of every application that uses it.

Example Scenario

Let’s explore an example scenario where we assume that there is 1GiB of shared library code mapped into your application's virtual address space. For this example, there are three important things to consider. First, let's assume that there is 2.5GiB of physical memory available. Second, the application has a 4GiB virtual address space, but 1GiB of that is used up by shared code that is mapped into the virtual address space. Finally, there is the relationship between the view of the virtual address space compared to the available physical memory. The state that this example starts in is a 3GiB view of available virtual memory, with 2.5GiB of memory available to physically back it.

There is the obvious problem here that the application thinks there is 3GiB of memory free, but there is only 2.5GiB of physical memory that’s free. If the application tries to allocate over 2.5GiB, it would crash due to running out of physical memory.

Let's assume that the application only allocates up to the 2.5GiB mark and never runs out of physical memory. This would be fine if the app could just linearly allocate as much memory as is physically available. But, if an application is doing a decent number of allocations (and is actively freeing those allocations) the virtual address space gets fragmented. Most applications crash from memory pressure because the virtual address space gets fragmented, not because of lack of physical memory.

For example there might be 500MiB of virtual address ranges available, but broken up into 100 non-contiguous chunks of 50MiB each. If the application tries to allocate 75MiB it will crash, even though there is ample physical memory to back that allocation and despite the virtual address space having 500MiB of total memory available.

With a 64-bit build, the virtual address space is 18.4 exabytes. This (virtually) eliminates memory pressure (memory fragmentation) from the virtual address space. It simplifies the way we have to think about memory because the biggest consideration becomes the amount of physical memory that’s available to back that 18.4 exabyte virtual address space. This is a very compelling factor in moving to 64-bit builds, no more memory pressure from virtual address space fragmentation.

Of course, this is all very much over-simplified. The amount of fragmentation isn’t just bound to allocations by the application, the various heaps that Android maintains plays a role here. There is also the question of when physical memory has to back a virtual allocation. But this does give a good overview of how a 64-bit build is better for memory even though the available physical memory does not increase.

Feel free to share any questions in the comments section below and thanks for reading.

- Gabor Szauer