Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically retrieve memory usage on iPhone

I'm trying to retrieve the amount of memory my iPhone app is using at anytime, programmatically. Yes I'm aware about ObjectAlloc/Leaks. I'm not interested in those, only to know if it's possible to write some code and get the amount of bytes being used and report it via NSLog.

Thanks.

like image 375
Coocoo4Cocoa Avatar asked Apr 24 '09 19:04

Coocoo4Cocoa


People also ask

How do I check my memory usage on iOS?

Go to Settings > General > [Device] Storage. You might see a list of recommendations for optimizing your device's storage, followed by a list of installed apps and the amount of storage each one uses. Tap an app's name for more information about its storage. Cached data and temporary data might not be counted as usage.

How do I keep track of memory usage?

To open up Resource Monitor, press Windows Key + R and type resmon into the search box. Resource Monitor will tell you exactly how much RAM is being used, what is using it, and allow you to sort the list of apps using it by several different categories.


2 Answers

To get the actual bytes of memory that your application is using, you can do something like the example below. However, you really should become familiar with the various profiling tools as well as they are designed to give you a much better picture of usage over-all.

#import <mach/mach.h>  // ...  void report_memory(void) {   struct task_basic_info info;   mach_msg_type_number_t size = TASK_BASIC_INFO_COUNT;   kern_return_t kerr = task_info(mach_task_self(),                                  TASK_BASIC_INFO,                                  (task_info_t)&info,                                  &size);   if( kerr == KERN_SUCCESS ) {     NSLog(@"Memory in use (in bytes): %lu", info.resident_size);     NSLog(@"Memory in use (in MiB): %f", ((CGFloat)info.resident_size / 1048576));   } else {     NSLog(@"Error with task_info(): %s", mach_error_string(kerr));   } } 

There is also a field in the structure info.virtual_size which will give you the number of bytes available virtual memory (or memory allocated to your application as potential virtual memory in any event). The code that pgb links to will give you the amount of memory available to the device and what type of memory it is.

like image 148
Jason Coco Avatar answered Sep 24 '22 21:09

Jason Coco


This has been tested on Xcode 11 in Mojave 10.4.6 on 07/01/2019, and on Xcode 11.3 as of 11/05/2020

All of the previous answers return the incorrect result.

Two Swift versions are below.

Here is how to get the expected value written by Apple's Quinn “The Eskimo!”.

This uses the phys_footprint var from Darwin > Mach > task_info and closely matches the value in the memory gauge in Xcode's Debug navigator.

The value returned is in bytes.

https://forums.developer.apple.com/thread/105088#357415

Original code follows.

func memoryFootprint() -> mach_vm_size_t? {       // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too       // complex for the Swift C importer, so we have to define them ourselves.       let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)       let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout<integer_t>.size)       var info = task_vm_info_data_t()       var count = TASK_VM_INFO_COUNT       let kr = withUnsafeMutablePointer(to: &info) { infoPtr in           infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in               task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)           }       }       guard           kr == KERN_SUCCESS,           count >= TASK_VM_INFO_REV1_COUNT       else { return nil }       return info.phys_footprint   }   

Modifying this slightly to create a class level set of Swift methods allows easy return of the actual bytes and formatted output in MB for display. I use this as part of an automated UITest suite to log memory used before and after multiple iterations of the same test to see if we have any potential leaks or allocations we need to look into.

//  Created by Alex Zavatone on 8/1/19. //  class Memory: NSObject {      // From Quinn the Eskimo at Apple.     // https://forums.developer.apple.com/thread/105088#357415      class func memoryFootprint() -> Float? {         // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too         // complex for the Swift C importer, so we have to define them ourselves.         let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)         let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout<integer_t>.size)         var info = task_vm_info_data_t()         var count = TASK_VM_INFO_COUNT         let kr = withUnsafeMutablePointer(to: &info) { infoPtr in             infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in                 task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)             }         }         guard             kr == KERN_SUCCESS,             count >= TASK_VM_INFO_REV1_COUNT             else { return nil }                  let usedBytes = Float(info.phys_footprint)         return usedBytes     }          class func formattedMemoryFootprint() -> String     {         let usedBytes: UInt64? = UInt64(self.memoryFootprint() ?? 0)         let usedMB = Double(usedBytes ?? 0) / 1024 / 1024         let usedMBAsString: String = "\(usedMB)MB"         return usedMBAsString      } } 

Enjoy!

Note: an enterprising coder may want to add a static formatter to the class so that usedMBAsString only returns 2 significant decimal places.

like image 26
Alex Zavatone Avatar answered Sep 22 '22 21:09

Alex Zavatone