Ale*_*man 2 memory xcode memory-profiling ios
根据我到目前为止所读的内容,实际/驻留字节表示分配给应用程序的字节数,包括该应用程序不再使用但尚未被OS回收的字节。活动/脏字节是应用程序实际使用且操作系统无法回收的字节。我认为XCode Debug导航器中显示的数字是“实时字节”。
我有兴趣通过编程方式获取此数字(用于我们自己的统计信息/分析),但是我发现的代码只能提供常驻字节的值,该值大于Xcode在某些设备上显示的值(几乎是两倍) ),实际上是在相同设备上,但iOS版本不同。(在iOS 9上,它的值几乎是它的两倍,但在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));
}
Run Code Online (Sandbox Code Playgroud)
是否有一些代码来获取实时字节值(如Xcode所示)?
我发现了其他东西,但似乎可以在该设备上使用前一种方法不起作用,并且不能在该设备上使用前一种方法起作用:-(现在,我需要弄清楚如何知道要使用哪种方法。一种设备是装有iOS 9的iPhone 5s,另一种是装有iOS 11的iPhone 5s。我想我需要在更多种类的设备上进行测试...
我在这里找到它:
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;
Run Code Online (Sandbox Code Playgroud)
我认为,如果我添加vmInfo.internal和vmInfo.compressed,那么我会得到正确的结果(与Xcode Debug导航器显示的内容匹配)
到目前为止,对于这两个设备以及我测试的其他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));
}
Run Code Online (Sandbox Code Playgroud)
由于对 Darwin 类型的访问在 Obj-C 和 Swift 中看起来略有不同,所以我想添加我根据Alex 的答案在 Swift 中提出的解决方案:
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)");
}
Run Code Online (Sandbox Code Playgroud)
该代码基于和 的类似答案。mach_task_basic_inforesident_size