obsidian/笔记文件/2.笔记/ios获取内存相关.md
2025-04-07 15:13:46 +08:00

249 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ios
#unity/日常积累
ios相关逻辑
头文件:
## MemoryInfoPlugin.h
``` objc
#import <Foundation/Foundation.h>
@interface MemoryInfoPlugin : NSObject
+ (NSString *)getMemoryInfo;
+ (double)getUsedMemoryMB;
+ (double)getTotalMemoryMB;
+ (double)getMemoryUsagePercentage;
@end
```
## MemoryInfoPlugin.mm
``` objc
#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性能检测工具]]确认性能数据,是否准确