obsidian/笔记文件/2.笔记/ios获取内存相关.md

249 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

2025-03-26 17:54:55 +08:00
#ios
#unity/日常积累
ios相关逻辑
头文件:
## MemoryInfoPlugin.h
2025-04-07 15:13:46 +08:00
``` objc
2025-03-26 17:54:55 +08:00
#import <Foundation/Foundation.h>
@interface MemoryInfoPlugin : NSObject
+ (NSString *)getMemoryInfo;
+ (double)getUsedMemoryMB;
+ (double)getTotalMemoryMB;
+ (double)getMemoryUsagePercentage;
@end
```
## MemoryInfoPlugin.mm
2025-04-07 15:13:46 +08:00
``` objc
2025-03-26 17:54:55 +08:00
#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
``` 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() + "%");
}
}
```
相关目录结构:
![[Pasted image 20250326153420.png]]
![[Pasted image 20250326153443.png]]
最终xcode运行效果
![[Pasted image 20250326153542.png]]
## 相关逻辑解析
这个获取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+可用
- 如果需支持更老版本,需要添加条件编译:
``` cpp
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
return taskInfo.phys_footprint;
#else
return taskInfo.internal + taskInfo.compressed;
#endif
```
这个实现方式是目前iOS平台最准确可靠的内存统计方案被主流性能监控工具广泛采用。
也可配合[[xcode性能检测工具]]确认性能数据,是否准确