当前位置:  开发笔记 > IOS > 正文

以编程方式检索iPhone上的内存使用情况

如何解决《以编程方式检索iPhone上的内存使用情况》经验,为你挑选了5个好方法。

我正在尝试以编程方式随时检索我的iPhone应用程序正在使用的内存量.是的我知道ObjectAlloc/Leaks.我对这些不感兴趣,只知道是否可以编写一些代码并获取正在使用的字节数并通过NSLog报告.

谢谢.



1> Jason Coco..:

要获取应用程序正在使用的实际内存字节数,您可以执行类似下面的示例.但是,您真的应该熟悉各种分析工具,并且它们旨在让您更好地了解使用情况.

#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链接到的代码将为您提供设备可用的内存量以及它的内存类型.


在我的情况下,返回的数量是XCode推出的内存报告的两倍多.不知道该怎么做.
谢谢,正是我在寻找的东西.这种方法应用商店安全吗?
如果您使用Cmd + Click task_basic_info,那么现在似乎不应该使用它并替换为mach_task_basic_info.我的猜测是这个版本与64位架构不兼容,但不是很确定.

2> combinatoria..:

标题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));
    }
}



3> Doug Null..:

这是增强的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;
}


大小应该是TASK_BASIC_INFO_COUNT而不是sizeof(info) - 这个错误被复制粘贴到许多地方使用相同的代码

4> Nazariy Vliz..:

快速解决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))")
    }
}



5> Alex Zavaton..:

已在07/01/2019在Mojave 10.4.6的Xcode 11上进行了测试。

先前的所有答案均返回错误的结果

这是如何获得苹果公司的奎因(Quinn)“爱斯基摩人”(The Eskimo!)所写的期望值的方法。

它使用phys_footprintvar中的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个有效的小数位。

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有