xcode 在iOS应用程序中以编程方式获取内存使用情况Live/Dirty Bytes(不是Resident/真实的Bytes)

vxbzzdmp  于 2023-04-22  发布在  iOS
关注(0)|答案(2)|浏览(73)

根据我目前所读到的,真实的/resident bytes表示分配给应用程序的字节数,包括应用程序不再使用但操作系统尚未回收的字节。而live/dirty bytes是应用程序实际使用且操作系统无法回收的字节。我认为XCode Debug导航器中显示的数字是Live Bytes。
我对通过编程得到这个数字很感兴趣(用于我们自己的统计/分析),但我找到的代码只能给予驻留字节的值,这比Xcode在某些设备上显示的值要大(几乎两倍是大的),实际上在相同的设备上,但不同的iOS版本。(在iOS 9上,它给出的值几乎是Xcode的两倍,但在iOS 11上,它给出的值几乎与Xcode相同)。
我使用的代码是这样的:

struct mach_task_basic_info info;
mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(),
                               MACH_TASK_BASIC_INFO,
                               (task_info_t)&info,
                               &size);
if( kerr == KERN_SUCCESS ) {
    NSLog(@"Memory in use (in bytes): %u", info.resident_size);
    return info.resident_size;
} else {
    NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}

是否有一些代码可以像Xcode显示的那样获取live bytes值?

mbskvtky

mbskvtky1#

我发现了别的东西,但它似乎工作在设备上,以前的方法没有工作,而不是工作在设备上,以前的方法没有工作:-(现在我需要弄清楚如何知道使用哪一个.一个设备是iPhone 5s与iOS 9和另一个是iPhone 5s与iOS 11.我想我需要测试更多veriaty的设备...
我在这里找到了:
https://opensource.apple.com/source/WebKit/WebKit-7603.1.30.1.33/ios/Misc/MemoryMeasure.mm.auto.html
这在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;

我想如果我添加vmInfo.internal和vmInfo.compressed,那么我将得到正确的结果(与XcodeDebug导航器显示的内容相匹配)
到目前为止,它看起来适合这两个设备,以及我测试的其他2个设备。
所以我的最终代码看起来像这样:

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));
}
kiayqfof

kiayqfof2#

由于访问达尔文类型在Obj-C和Swift中看起来略有不同,我想添加我在Swift中基于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 = Int(vmInfo.internal + vmInfo.compressed)
    print("Memory in use: \(usedSize) bytes")
} else {
    let errorString = String(cString: mach_error_string(kern), encoding: .ascii) ?? "unknown error"
    print("Error with task_info(): \(errorString)");
}

这段代码基于类似的answer,有mach_task_basic_inforesident_size

相关问题