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

4.1 KiB
Raw Permalink Blame History

#安卓 #unity/日常积累

移动端存在几个不同的内存获取方式USS、PSS、RSS他们之间的区别

对于USSUnique Set Size计算了TotalPrivateDirty和TotalPrivateClean的总和再转换为MB。USS指的是进程独占的物理内存不包含共享库的部分这部分是正确的。

PSSProportional Set Size是共享内存按比例分配后的值比如三个进程共享一个库每个进程的PSS会加上该库大小的1/3。这也是正确的实现。

RSS实际物理内存占用通过读取/proc/self/status中的VmRSS来获取这是更直接且准确的方式因为系统提供的这个值直接反映了RSS的大小。

!Pasted image 20250407142019.png

逻辑参考:

    //获取USS
    public static int getUSSMemoryMB()
    {
        try {
//            if (!hasUsageStatsPermission()) {
//                return -2;
//            }
            int pid = android.os.Process.myPid();
            Activity activity = UnityActivity.getActivity();
            ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
            Debug.MemoryInfo[] memInfoArray = am.getProcessMemoryInfo(new int[]{pid});
            if (memInfoArray != null && memInfoArray.length > 0)
            {
                Debug.MemoryInfo mi = memInfoArray[0];
                int ussKb = mi.getTotalPrivateDirty() + mi.getTotalPrivateClean();
                return ussKb / 1024; //转MB
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        return -1;
    }
    
    // 获取 PSSMB
    public static int getPSSMemoryMB() {
        try {
//            if (!hasUsageStatsPermission()) {
//                return -2;
//            }
            int pid = android.os.Process.myPid();
            Activity activity = UnityActivity.getActivity();
            ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
            Debug.MemoryInfo[] memInfoArray = am.getProcessMemoryInfo(new int[]{pid});
            if (memInfoArray != null && memInfoArray.length > 0) {
                return memInfoArray[0].getTotalPss() / 1024; // 转换为MB
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    
    // 获取 RSSMB
    public static int getRSSMemoryMBProc() {  
//        long startTime = System.nanoTime(); // 记录开始时间  
        try (BufferedReader br = new BufferedReader(new FileReader("/proc/self/status"))) {  
            String line;  
            while ((line = br.readLine()) != null) {  
                if (line.startsWith("VmRSS:")) {  
                    String[] parts = line.split("\\s+");  
                    int kb = Integer.parseInt(parts[1]);  
                    //                    long duration = (System.nanoTime() - startTime) / 1000; // 微秒耗时  
//                    Log.d("PerfMonitor", "getRSSMemoryMBProc took " + duration + "μs");  
                    return kb / 1024;  
                }  
            }  
            // 如果没有找到VmRSS行也记录耗时  
//            long duration = (System.nanoTime() - startTime) / 1000;  
//            Log.d("PerfMonitor", "getRSSMemoryMBProc (no data) took " + duration + "μs");  
        } catch (Exception e) {  
//            long duration = (System.nanoTime() - startTime) / 1000;  
//            Log.e("PerfMonitor", "getRSSMemoryMBProc failed after " + duration + "μs", e);  
            e.printStackTrace();  
        }  
        return -1;  
    }
    // 获取系统可用内存百分比
    public float getAvailableMemoryPercent() {
        ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
        Activity activity = UnityActivity.getActivity();
        ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        am.getMemoryInfo(mi);
        return (float)mi.availMem / mi.totalMem * 100;
    }

安卓相关的Manifest.xml文件也添加一下权限申请

!Pasted image 20250407143343.png