AndroidAPK内存优化删减

来源:互联网 发布:淘宝助理打印设置 编辑:程序博客网 时间:2024/05/01 23:49

AndroidAPK内存优化删减

1、使用场景(内存)

1APK启动应用时内存占用及分布,即初始化时(如内核初始化,外围资源加载等)各占多少

2)使用APK核心功能时内存占用及分布,如UI加载,数据加载保存

3)用户常用操作时内存占用及分布

2通过命令查看内存占用及分布

1)命令:adbshell dumpsys meminfo yourpakagename

终端输入命令后,可以看到类似下图的结果


改命令实际的调用代码入口在android.os.Debug.java和对应的CPP文件android_os_Debug.cppDebug.javagetMeminfo方法实际上调用了android_os_Debug.cppandroid_os_Debug_getDirtyPagesPid方法。

static voidandroid_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, jintpid, jobject object){stats_tstats[_NUM_HEAP];memset(&stats,0, sizeof(stats));load_maps(pid,stats);structgraphics_memory_pss graphics_mem;if(read_memtrack_memory(pid, &graphics_mem) == 0) {...}...}static voidload_maps(int pid, stats_t* stats){chartmp[128];FILE *fp;sprintf(tmp,"/proc/%d/smaps", pid);fp =fopen(tmp, "r");if (fp ==0) return;read_mapinfo(fp,stats);fclose(fp);}


           从上面的代码可以看到,android_os_Debug_getDirtyPagesPid方法先调用了load_maps方法,而load_maps方法要做的事情也很简单,它打开/proc/PID/smaps虚拟文件,读取里面的信息,在已ROOT的设备上,我们可以通过“adbshell cat /proce/PID/smaps”直接将这个虚拟文件的信息打印在控制台上。

       “adb shell cat/proce/PID/smaps”输出的信息实际上是应用的userspace地址空间的内存分配表,记录了应用分配的每一块内存的地址,类别,大小等信息,而load_maps方法调用read_mapinfo方法从这个表里面读出每一块内存的分配信息,分类进行累加,得出Native HeapDalvikHeap等各个类别的内存占用。

           更多具体讲解可以参考:http://tech.uc.cn/?p=2714

我们可以使用脚本smaps解析得到更简化的内存数据分布。

2)命令:adbshell procrank

通过该命令可以获取所有进程的内存占用:



linux下表示内存的耗用情况有四种不同的表现形式:
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

VSSVSS表示一个进程可访问的全部内存地址空间的大小。这个大小包括了进程已经申请但尚未使用的内存空间。在实际中很少用这种方式来表示进程占用内存的情况,用它来表示单个进程的内存使用情况是不准确的。
RSS表示一个进程在RAM中实际使用的空间地址大小,包括了全部共享库占用的内存,这种表示进程占用内存的情况也是不准确的。
PSS表示一个进程在RAM中实际使用的空间地址大小,它按比例包含了共享库占用的内存。假如有3个进程使用同一个共享库,那么每个进程的PSS就包括了1/3大小的共享库内存。这种方式表示进程的内存使用情况较准确,但当只有一个进程使用共享库时,其情况和RSS一模一样。
USS:表示一个进程本身占用的内存空间大小,不包含其它任何成分,这是表示进程内存大小的最好方式!
可以看到:VSS>=RSS>=PSS>=USS



Note:这里有一个问题需要注意,如果一个APK里面只使用了32位的so库文件,在64位的机器上运行,一般系统系统会兼容。但是对应的PSS内存可能会比使用64位的so所占用的内存大。因为在32位共享库占用的内存可能会全部算到该APKPSS内存里面(因为没有其他32APK按比例分配共享库内存)

3通过代码查看内存占用及分布

下面列举几种获取不同内存的方式:

publicstaticlongusedMemory() {finalRuntime s_runtime = Runtime.getRuntime();return(s_runtime.totalMemory() - s_runtime.freeMemory());}publicstaticintgetPssMemory(Context context) {finalActivityManager am = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);android.os.Debug.MemoryInfo[]memoryInfoArray = am.getProcessMemoryInfo(newint[]{android.os.Process.myPid()});returnmemoryInfoArray[0].getTotalPss();}/***Gets the total available memory (KB) on the system.*/publicstaticlonggetTotalAvailableMemory(Context context) {try{finalActivityManager am = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);ActivityManager.MemoryInfooutInfo = newActivityManager.MemoryInfo();am.getMemoryInfo(outInfo);return(long)outInfo.availMem/1024;}catch(Exceptione){return-1;}}/***Gets the total memory (KB) on the system.*/publicstaticlonggetTotalMemory(Context context) {try{finalActivityManager am = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);ActivityManager.MemoryInfooutInfo = newActivityManager.MemoryInfo();am.getMemoryInfo(outInfo);if(SystemPropertiesReflect.getSdkVersion()>= SystemPropertiesReflect.VERSION_CODES.JELLY_BEAN)return(long)outInfo.totalMem/1024;elsereturn-1;}catch(Exceptione){return-1;}}


4删减内存常见方法

1)删减无用代码及功能资源

2dex拆分(multidex/插件话/动态加载

3)使用外部进程(android:process

4)跑proguard,去掉无用的代码

5)缩减所使用的库的大小

6)尽量减少依赖的包

7)java代码优化
8)其他

原创粉丝点击