Getting memory usage Live/Dirty Bytes in iOS app programmatically (not Resident/Real Bytes)

喜夏-厌秋 提交于 2019-12-06 09:53:08

I found something else, but it seems to work on the device that the previous method didn't work and not work on the device that the previous method did work :-( Now I need to figure out how to know which one to use. One device is iPhone 5s with iOS 9 and another is iPhone 5s with iOS 11. I guess I need to test on more veriaty of devices...

I found it here:

https://opensource.apple.com/source/WebKit/WebKit-7603.1.30.1.33/ios/Misc/MemoryMeasure.mm.auto.html

This translated to something like this in Objective-C:

task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t err = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if (err != KERN_SUCCESS)
    return 0;

NSLog(@"Memory in use vmInfo.internal (in bytes): %u", vmInfo.internal);

return vmInfo.internal;

I think if I add vmInfo.internal and vmInfo.compressed then I'll get the right result (matching what Xcode Debug navigator is showing)

It looks right for these two devices so far, and 2 other devices I tested.

So my final code looks like this:

task_vm_info_data_t info;
mach_msg_type_number_t size = TASK_VM_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(),
                               TASK_VM_INFO,
                               (task_info_t)&info,
                               &size);
if( kerr == KERN_SUCCESS ) {
    mach_vm_size_t totalSize = info.internal + info.compressed;
    NSLog(@"Memory in use (in bytes): %u", totalSize);
    return totalSize;
} else {
    NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}

Since access to Darwin types looks slightly different in Obj-C and Swift I wanted to add the solution I came up in Swift based on Alex's answer:

let TASK_VM_INFO_COUNT = MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<natural_t>.size

var vmInfo = task_vm_info_data_t()
var vmInfoSize = mach_msg_type_number_t(TASK_VM_INFO_COUNT)

let kern: kern_return_t = withUnsafeMutablePointer(to: &vmInfo) {
        $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
            task_info(mach_task_self_,
                      task_flavor_t(TASK_VM_INFO),
                      $0,
                      &vmInfoSize)
            }
        }

if kern == KERN_SUCCESS {
    let usedSize = DataSize(bytes: Int(vmInfo.internal + vmInfo.compressed))
    print("Memory in use (in bytes): %u", usedSize)
} else {
    let errorString = String(cString: mach_error_string(kern), encoding: .ascii) ?? "unknown error"
    print("Error with task_info(): %s", errorString);
}

This code is based on similar answer with mach_task_basic_info and resident_size.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!