我正在尝试以编程方式随时检索我的iPhone应用程序正在使用的内存量.是的我知道ObjectAlloc/Leaks.我对这些不感兴趣,只知道是否可以编写一些代码并获取正在使用的字节数并通过NSLog报告.
谢谢.
要获取应用程序正在使用的实际内存字节数,您可以执行类似下面的示例.但是,您真的应该熟悉各种分析工具,并且它们旨在让您更好地了解使用情况.
#import// ... 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)); } }
在结构info.virtual_size中还有一个字段,它将为您提供可用虚拟内存的字节数(或在任何情况下分配给您的应用程序作为潜在虚拟内存的内存).pgb链接到的代码将为您提供设备可用的内存量以及它的内存类型.
标题TASK_BASIC_INFO
说:
/* Don't use this, use MACH_TASK_BASIC_INFO instead */
这是一个使用的版本MACH_TASK_BASIC_INFO
:
void report_memory(void) { 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); } else { NSLog(@"Error with task_info(): %s", mach_error_string(kerr)); } }
这是增强的report_memory(),以便在NSLog()中快速显示泄漏状态.
void report_memory(void) { static unsigned last_resident_size=0; static unsigned greatest = 0; static unsigned last_greatest = 0; struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); if( kerr == KERN_SUCCESS ) { int diff = (int)info.resident_size - (int)last_resident_size; unsigned latest = info.resident_size; if( latest > greatest ) greatest = latest; // track greatest mem usage int greatest_diff = greatest - last_greatest; int latest_greatest_diff = latest - greatest; NSLog(@"Mem: %10u (%10d) : %10d : greatest: %10u (%d)", info.resident_size, diff, latest_greatest_diff, greatest, greatest_diff ); } else { NSLog(@"Error with task_info(): %s", mach_error_string(kerr)); } last_resident_size = info.resident_size; last_greatest = greatest; }
快速解决Jason Coco的回答:
func reportMemory() { let name = mach_task_self_ let flavor = task_flavor_t(TASK_BASIC_INFO) let basicInfo = task_basic_info() var size: mach_msg_type_number_t = mach_msg_type_number_t(sizeofValue(basicInfo)) let pointerOfBasicInfo = UnsafeMutablePointer.alloc(1) let kerr: kern_return_t = task_info(name, flavor, UnsafeMutablePointer(pointerOfBasicInfo), &size) let info = pointerOfBasicInfo.move() pointerOfBasicInfo.dealloc(1) if kerr == KERN_SUCCESS { print("Memory in use (in bytes): \(info.resident_size)") } else { print("error with task info(): \(mach_error_string(kerr))") } }
已在07/01/2019在Mojave 10.4.6的Xcode 11上进行了测试。
先前的所有答案均返回错误的结果。
这是如何获得苹果公司的奎因(Quinn)“爱斯基摩人”(The Eskimo!)所写的期望值的方法。
它使用phys_footprint
var中的var Darwin > Mach > task_info
并与Xcode的Debug导航器中的内存量表中的值紧密匹配。
返回的值以字节为单位。
https://forums.developer.apple.com/thread/105088#357415
原始代码如下。
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.size / MemoryLayout .size) let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout .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 }
稍加修改即可创建一个类级别的Swift方法集,从而可以轻松返回实际字节和以MB为单位的格式化输出以供显示。我将其用作自动UITest套件的一部分,以记录在同一测试的多次迭代之前和之后使用的内存,以查看是否有潜在的泄漏或分配需要研究。
// 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.size / MemoryLayout .size) let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout .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 } }
请享用!
注意:进取的编码人员可能希望向该类添加静态格式化程序,以便usedMBAsString
仅返回2个有效的小数位。