当然,在 IOS 的限制下应用只能获取当前进程自身的内存信息。Google 了一阵后,发现大部分博客讲的都是 Object-C 如何获取内存信息,而我这边是用 Swift 开发的,于是尝试将 Object-C 的实现改为 Swift 实现,在此过程中遇到一些坑,记录一下。

IOS 使用 Object-C 实现获取内存信息

大致思路就是利用 task_info 系统接口来实现,我们可以参考 滴滴开源的 DoraemonKit 的实现

#include <mach/mach.h>

+ (NSInteger)useMemoryForApp{
    task_vm_info_data_t vmInfo;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
    kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
    if(kernelReturn == KERN_SUCCESS)
    {
        int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint;
        return (NSInteger)(memoryUsageInByte/1024/1024);
    }
    else
    {
        return -1;
    }
}


//设备总的内存
+ (NSInteger)totalMemoryForDevice{
    return (NSInteger)([NSProcessInfo processInfo].physicalMemory/1024/1024);
}

能看到,其实就是调用了 task_info() 获取到当前进程的信息,第一个参数为当前进程的 mach port,第二个参数是 TASK_VM_INFO,后面两个参数为返回值将引用传进去。

然后获取 task_vm_info_data_t 中的 phys_footprint 就是当前进程的内存占用单位是 byte,在 腾讯开源的 Matrix 也是差不多的实现。

感兴趣的小伙伴可以深入了解一下 task_info() 的实现。

IOS 使用 Swift 实现获取内存信息

按道理来说,这都有 Object-C 的代码了,将它改成 Swift 的实现不是就好了吗?我刚开始也是这么想的…先看看我处理好后的代码吧。

/// 获取内存使用情况
/// - Returns:
///     - used: 已使用
///     - total: 总内存
public static func memoryUsage() -> (used: UInt64, total: UInt64) {
    var taskInfo = task_vm_info_data_t()
    var count = mach_msg_type_number_t(MemoryLayout<task_vm_info>.size) / 4
    let result: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
        $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
            task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), $0, &count)
        }
    }

    var used: UInt64 = 0
    if result == KERN_SUCCESS {
        used = UInt64(taskInfo.phys_footprint)
    }

    let total = ProcessInfo.processInfo.physicalMemory
    return (used, total)
}

首先 TASK_VM_INFO_COUNT 常量找不到,这里使用 mach_msg_type_number_t(MemoryLayout<task_vm_info>.size) / 4 方式处理。

还有就是调用 task_info 时,需要使用 withMemoryRebound 来处理 task_vm_info_data_t 指针。

最后我这边是返回了总内存和当前进程已使用内存的元组。

参考链接

didi/DoraemonKit

Tencent/matrix

iOS 内存管理研究 - 知乎

iOS内存abort(Jetsam) 原理探究

macOS 内核之内存占用信息

Issues using withMemoryRebound in Swift 3