以编程方式获取 iOS 应用程序中的内存使用 Live/Dirty 字节(而不是 Resident/Real 字节)
Getting memory usage Live/Dirty Bytes in iOS app programmatically (not Resident/Real Bytes)
根据我目前所读的内容,real/resident 字节表示分配给应用程序的字节数,包括应用程序不再使用但尚未被 OS.
live/dirty 字节是应用程序实际使用的字节,OS 无法回收。
我认为 XCode Debug navigator 中显示的数字是 Live Bytes。
我有兴趣以编程方式获取这个数字(对于我们自己的 statistics/analytics),但是我找到的代码只能给出驻留字节的值,该值大于 Xcode 在某些设备上显示(几乎是大的两倍),实际上是在相同的设备上但不同的 iOS 版本。 (在 iOS 9 上,它给出的值几乎是 iOS 11 上的两倍,但在 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 显示的那样获取活动字节值?
我发现了其他东西,但它似乎在以前的方法不起作用的设备上工作,并且在以前的方法工作的设备上不起作用:-(
现在我需要弄清楚如何知道使用哪一个。一个设备是 iPhone 5s 和 iOS 9,另一个是 iPhone 5s 和 iOS 11。
我想我需要在更多设备上进行测试...
我在这里找到的:
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 那么我会得到正确的结果(匹配 Xcode 调试导航器显示的内容)
到目前为止,这两款设备以及我测试过的其他 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));
}
由于在 Obj-C 和 Swift 中访问 Darwin 类型看起来略有不同,我想添加我在 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) {
[=10=].withMemoryRebound(to: integer_t.self, capacity: 1) {
task_info(mach_task_self_,
task_flavor_t(TASK_VM_INFO),
[=10=],
&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);
}
此代码基于与 mach_task_basic_info
和 resident_size
相似的 answer。
根据我目前所读的内容,real/resident 字节表示分配给应用程序的字节数,包括应用程序不再使用但尚未被 OS. live/dirty 字节是应用程序实际使用的字节,OS 无法回收。 我认为 XCode Debug navigator 中显示的数字是 Live Bytes。
我有兴趣以编程方式获取这个数字(对于我们自己的 statistics/analytics),但是我找到的代码只能给出驻留字节的值,该值大于 Xcode 在某些设备上显示(几乎是大的两倍),实际上是在相同的设备上但不同的 iOS 版本。 (在 iOS 9 上,它给出的值几乎是 iOS 11 上的两倍,但在 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 显示的那样获取活动字节值?
我发现了其他东西,但它似乎在以前的方法不起作用的设备上工作,并且在以前的方法工作的设备上不起作用:-( 现在我需要弄清楚如何知道使用哪一个。一个设备是 iPhone 5s 和 iOS 9,另一个是 iPhone 5s 和 iOS 11。 我想我需要在更多设备上进行测试...
我在这里找到的:
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 那么我会得到正确的结果(匹配 Xcode 调试导航器显示的内容)
到目前为止,这两款设备以及我测试过的其他 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));
}
由于在 Obj-C 和 Swift 中访问 Darwin 类型看起来略有不同,我想添加我在 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) {
[=10=].withMemoryRebound(to: integer_t.self, capacity: 1) {
task_info(mach_task_self_,
task_flavor_t(TASK_VM_INFO),
[=10=],
&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);
}
此代码基于与 mach_task_basic_info
和 resident_size
相似的 answer。