5.7 KiB
5.7 KiB
#ios #unity/日常积累
ios相关逻辑 头文件:
MemoryInfoPlugin.h
#import <Foundation/Foundation.h>
@interface MemoryInfoPlugin : NSObject
+ (NSString *)getMemoryInfo;
+ (double)getUsedMemoryMB;
+ (double)getTotalMemoryMB;
+ (double)getMemoryUsagePercentage;
@end
MemoryInfoPlugin.mm
#import "MemoryInfoPlugin.h"
#import <mach/mach.h>
#import <sys/sysctl.h>
@implementation MemoryInfoPlugin
+ (NSString *)getMemoryInfo {
double used = [self getUsedMemoryMB];
double total = [self getTotalMemoryMB];
double percentage = [self getMemoryUsagePercentage];
return [NSString stringWithFormat:@"已使用: %.2f MB, 总共: %.2f MB, 使用率: %.2f%%",
used, total, percentage];
}
+ (double)getUsedMemoryMB {
task_vm_info_data_t taskInfo;
mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT;
kern_return_t kernReturn = task_info(mach_task_self(),
TASK_VM_INFO,
(task_info_t)&taskInfo,
&infoCount);
if (kernReturn != KERN_SUCCESS) {
return -1.0;
}
return (double)taskInfo.phys_footprint / 1024.0 / 1024.0;
}
+ (double)getTotalMemoryMB {
int64_t memorySize = 0;
size_t size = sizeof(memorySize);
sysctlbyname("hw.memsize", &memorySize, &size, NULL, 0);
return (double)memorySize / 1024.0 / 1024.0;
}
+ (double)getMemoryUsagePercentage {
double used = [self getUsedMemoryMB];
double total = [self getTotalMemoryMB];
if (total > 0) {
return (used / total) * 100.0;
}
return -1.0;
}
// 为Unity导出C函数
extern "C" {
const char* _GetMemoryInfo() {
NSString *info = [MemoryInfoPlugin getMemoryInfo];
return strdup([info UTF8String]);
}
double _GetUsedMemoryMB() {
return [MemoryInfoPlugin getUsedMemoryMB];
}
double _GetTotalMemoryMB() {
return [MemoryInfoPlugin getTotalMemoryMB];
}
double _GetMemoryUsagePercentage() {
return [MemoryInfoPlugin getMemoryUsagePercentage];
}
}
@end
调用 测试用例
IOSMemoryInfo.cs
using System.Runtime.InteropServices;
using UnityEngine;
public class IOSMemoryInfo : MonoBehaviour
{
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")]
private static extern string _GetMemoryInfo();
[DllImport("__Internal")]
private static extern double _GetUsedMemoryMB();
[DllImport("__Internal")]
private static extern double _GetTotalMemoryMB();
[DllImport("__Internal")]
private static extern double _GetMemoryUsagePercentage();
#endif
// 获取完整内存信息字符串
public static string GetMemoryInfo()
{
#if UNITY_IOS && !UNITY_EDITOR
return _GetMemoryInfo();
#else
return "仅支持iOS设备";
#endif
}
// 获取已使用内存(MB)
public static double GetUsedMemoryMB()
{
#if UNITY_IOS && !UNITY_EDITOR
return _GetUsedMemoryMB();
#else
return -1;
#endif
}
// 获取总内存(MB)
public static double GetTotalMemoryMB()
{
#if UNITY_IOS && !UNITY_EDITOR
return _GetTotalMemoryMB();
#else
return -1;
#endif
}
// 获取内存使用百分比
public static double GetMemoryUsagePercentage()
{
#if UNITY_IOS && !UNITY_EDITOR
return _GetMemoryUsagePercentage();
#else
return -1;
#endif
}
// 使用示例
void Start()
{
InvokeRepeating("ShowMemoryInfo", 1.0f, 5.0f);
}
void ShowMemoryInfo()
{
Debug.Log("内存信息: " + GetMemoryInfo());
Debug.Log("已使用: " + GetUsedMemoryMB() + " MB");
Debug.Log("总内存: " + GetTotalMemoryMB() + " MB");
Debug.Log("使用率: " + GetMemoryUsagePercentage() + "%");
}
}
相关目录结构:
最终xcode运行效果:
相关逻辑解析
这个获取iOS内存占用的方法有效,主要基于以下几个关键点:
1. Mach API的使用:
task_info(mach_task_self(), TASK_VM_INFO, ...)
这是iOS/macOS底层Mach内核提供的API,可以直接访问进程的内存信息。Mach是XNU内核的核心组件,专门负责内存管理等基础服务。
2. phys_footprint字段:
taskInfo.phys_footprint
这是Apple在iOS 9+引入的专用字段,表示:
-
实际物理内存使用量(非虚拟内存)
-
包含压缩内存(Compressed Memory)
-
包含IOKit使用的内存
-
符合Xcode Memory Report的统计标准
3. 与系统监控的一致性:
这个数值与Xcode Debug Gauges显示的内存值完全一致,是Apple官方推荐的内存统计方式。相比过时的resident_size字段,phys_footprint能更准确地反映真实内存使用情况。
4. 权限处理:
mach_task_self()
通过获取当前进程的task端口,避免了越权访问的问题,符合iOS的沙盒安全机制。
5. 单位转换:
/ 1024.0 / 1024.0
将字节转换为MB的经典处理方式(1MB = 1024KB = 10241024B)
需要注意的版本适配:
-
phys_footprint在iOS 9.0+可用
-
如果需支持更老版本,需要添加条件编译:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
return taskInfo.phys_footprint;
#else
return taskInfo.internal + taskInfo.compressed;
#endif
这个实现方式是目前iOS平台最准确可靠的内存统计方案,被主流性能监控工具广泛采用。 也可配合xcode性能检测工具确认性能数据,是否准确