70

You've likely seen the many "System Info" apps out there which display things like remaining battery life, and even system info like memory, etc.

In a similar manner, is there any way to retrieve the current amount of available RAM from my app so that I can make better decisions on when it's best to dump or keep certain views to avoid memory warnings?

bneely
  • 9,083
  • 4
  • 38
  • 46
m0rtimer
  • 2,023
  • 1
  • 25
  • 31
  • 3
    Or maybe you haven’t searched well enough ;-) http://stackoverflow.com/questions/3823266/is-it-legal-to-use-the-well-known-free-memory-code-in-ipad-iphone-app –  Feb 17 '11 at 07:13
  • 4
    @Bavarious: The answers to that and other related questions largely miss the point, which is that you might want to use more RAM to make your app more responsive or media-rich, etc., but only on devices that can comfortably accommodate the extra load. The advice to "profile" and "use less RAM" doesn't cut it. – Marcelo Cantos Dec 05 '11 at 11:15
  • @Eric: I had a similar issue and ended up finding an answer myself. See [here](http://stackoverflow.com/a/8072278/9990). Note that I was looking for total system RAM; I don't if that's the same as your requirement, but I hope this helps. – Marcelo Cantos Dec 05 '11 at 11:17
  • Does this answer your question? [Programmatically retrieve memory usage on iPhone](https://stackoverflow.com/questions/787160/programmatically-retrieve-memory-usage-on-iphone) – Top-Master Oct 14 '21 at 05:58
  • **See [only solution for extensions](https://stackoverflow.com/a/57315975/8740349)** (without wrong result) – Top-Master Oct 14 '21 at 05:59

3 Answers3

139
#import <mach/mach.h>
#import <mach/mach_host.h>

void print_free_memory ()
{
    mach_port_t host_port;
    mach_msg_type_number_t host_size;
    vm_size_t pagesize;

    host_port = mach_host_self();
    host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    host_page_size(host_port, &pagesize);        

    vm_statistics_data_t vm_stat;

    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
        NSLog(@"Failed to fetch vm statistics");
    }

    /* Stats in bytes */ 
    natural_t mem_used = (vm_stat.active_count +
                          vm_stat.inactive_count +
                          vm_stat.wire_count) * pagesize;
    natural_t mem_free = vm_stat.free_count * pagesize;
    natural_t mem_total = mem_used + mem_free;
    NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);
}

Please note that this call does not account for memory that is being used by the gpu. If you are seeing a size that is smaller than expected system ram. It is more than likely allocated graphics memory.

Nico
  • 3,826
  • 1
  • 21
  • 31
  • I'm shocked that I'm the first person to give you a point on this code. Its working great on my iPhone and is a huge help to me! I wish I could give you 10 points!!! – David H Mar 19 '12 at 16:18
  • I did find one other command you can add to the above, to get task stats: struct task_basic_info info; if(dump_memory_usage(&info)) { fm.resident_size = (size_t)info.resident_size; fm.virtual_size = (size_t)info.virtual_size; } – David H Jul 25 '12 at 12:06
  • 6
    If you want to true TOTAL RAM the device has, just use [NSProcessInfo processInfo].physicalMemory. – Steve Oct 01 '13 at 21:31
  • @Steve, Provides the amount of physical memory on the computer. - (unsigned long long)physicalMemory How does this tell you how much memory your application is using? – Nico Oct 01 '13 at 23:25
  • @Nico, it doesn't. It tells the total system RAM. I recommend this instead of mem_total/mem_free, not instead of mem_used. This is because mem_total/mem_free depend on how much RAM is being used by other apps to, and so it's a completely unreliable indicator for pretty much anything. – Steve Oct 02 '13 at 15:45
  • @Steve The nice part about mem_total is shrinks graphics memory is allocated – Nico Oct 02 '13 at 15:49
  • There are no private apis called here so yes. – Nico Nov 19 '13 at 17:47
  • Has anyone check that this code works correct at 64bit devices? – alexandrmoroz May 07 '15 at 09:25
  • 1
    I believe the total memory calculation is inaccurate. Cross-reference it with `[NSProcessInfo processInfo].physicalMemory` and you'll see the latter is more closely aligned with the device's marketed memory spec. – Thomas Elliot Feb 20 '19 at 04:38
  • @Nico which one is relevant NSProcessInfo processInfo].physicalMemory ,this one gives in bytes? – Srishti Roy Sep 17 '19 at 12:04
  • YES. NSProcessInfo processInfo].physicalMemory returns you total RAM size in bytes. – Jeba Moses Jan 17 '20 at 14:02
14

This works in Swift 4.

The really important difference here is: It casts to Int64 before multiplying, because otherwise you get quickly overflows, especially if you run it in a simulator where it uses the PC Memory.

var pagesize: vm_size_t = 0

let host_port: mach_port_t = mach_host_self()
var host_size: mach_msg_type_number_t = mach_msg_type_number_t(MemoryLayout<vm_statistics_data_t>.stride / MemoryLayout<integer_t>.stride)
host_page_size(host_port, &pagesize)

var vm_stat: vm_statistics = vm_statistics_data_t()
withUnsafeMutablePointer(to: &vm_stat) { (vmStatPointer) -> Void in
    vmStatPointer.withMemoryRebound(to: integer_t.self, capacity: Int(host_size)) {
        if (host_statistics(host_port, HOST_VM_INFO, $0, &host_size) != KERN_SUCCESS) {
            NSLog("Error: Failed to fetch vm statistics")
        }
    }
}

/* Stats in bytes */
let mem_used: Int64 = Int64(vm_stat.active_count +
        vm_stat.inactive_count +
        vm_stat.wire_count) * Int64(pagesize)
let mem_free: Int64 = Int64(vm_stat.free_count) * Int64(pagesize)
Jan
  • 1,032
  • 11
  • 26
  • 2
    Hello I tried your example but I have very different values for mem_used. When I convert it to MB, it gives me 120MB while in XCode, it gives me 30MB. Any idea why? – Mathias Van Houtte Jul 31 '18 at 07:46
  • Thanks for this. Just a comment, I think the Int64 should be UInt64. – Kleomenis Katevas Apr 09 '19 at 09:27
  • 1
    @Minos I disagree. Remember that 2^63 is already 9,223,372,036,854,775,808 and Int64 has as signed integer the advantage that some subtractions won't produce exceptions when going below 0. – Jan Apr 09 '19 at 09:39
  • Why `MemoryLayout.stride` instead of `MemoryLayout.size`? – Ky - Jan 17 '22 at 22:14
4

You can check the available RAM Memory in an iOS devices

    #import mach\mach.h
    #import mach\mach_host.h

     static natural_t get_free_memory(void)  
     {  
       mach_port_t host_port;  
       mach_msg_type_number_t host_size;  
       vm_size_t pagesize;  
       host_port = mach_host_self();  
       host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);  
       host_page_size(host_port, &pagesize);  
       vm_statistics_data_t vm_stat;  
       if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)  
       {  
         NSLog(@"Failed to fetch vm statistics");  
         return 0;  
       }  
       /* Stats in bytes */  
       natural_t mem_free = vm_stat.free_count * pagesize;  
       return mem_free;  
     }  
laxonline
  • 2,657
  • 1
  • 20
  • 37