iOS内存的深入探究(WWDC 2018 session 416)

iOS内存的深入探究(WWDC 2018 session 416),第1张

虚拟地址空间是指虚拟的、人们想象出来的地址空间,其实它并不存在,每个进程都有自己独立的虚拟空间,每个进程只能访问自己的地址空间,这样就能有效的做到了进程的 隔离

注: 虚拟储存的实现需要依赖硬件的支持,对于不同的CPU来说不同,但是几乎所有的硬件都采用MMU(Memory Management Unit)的部件来进行页映射。

把一段与程序所需要的内存空间大小的虚拟空间映射到某个地址空间。

当一个程序运行时,在某个时间段内,它只是频繁的用到了一小部分数据,程序的很多数据其实在一个时间段内都不会被用到。人们很自然的想到了更小粒度的内存分割和映射的方法,使得程序的局部性原理得到充分的利用,大大提高了内存的使用率。

原先的32位地址只能访问最多4GB的物理内存,但是自从扩展至36位地址线以后,Intel修改了页映射方式,使得新的映射方式可以访问到更多的物理内存,Intel把这个地址扩展方式叫做PAE(Physical Address Extension)

应用程序可以根据需求来选择申请和映射,比如一个应用程序0x10000000 ~0x20000000这一段256MB的虚拟地址空间用来做窗口,程序可以从高4GB的物理空间申请多个大小为256MB的物理空间,编号成A、B、C的等,然后根据需要将这个窗口映射到不同物理空间块,用到A时映射到A,用到B、C时再映射过去,叫做AWE(Address Windowing Extension),而Linux等UNIX类 *** 作系统则采用mmap()系统调用来实现

一些存储在磁盘中的数据,在CPU执行这个地址指令时,发现页面是一个空的页面,于是他就认为这是一个 页错误 ,CPU将控制权交给 *** 作系统, *** 作系统有专门处理例程来处理, *** 作系统将查询这个数据结构,然后找到空页面所在的VMA,计算相应的页面在可执行文件中的偏移,然后再物理内存中分配一个物理页面,将进程中该虚拟页与分配的物理页之间建立映射,然后再交给进程去执行。

ELF文件被映射时,是以页长度为单位的,每个段在映射时的长度应该是系统页长度的整倍数,如果不是,多余的部分页将占领一个页,造成了内存空间的大量浪费。而在ELF文件中,段的权限直邮为数不多的几种组合:

那么对于相同的段,我们把他们合并在一起当成一个段来映射,ELF可执行文件引入一个概念叫做Segment,一个segment包含一个或多个section,这样很明显的减少了页面内部的碎片,节省了空间

假设一个ELF执行文件,它有三个段需要装载,SEG0 、SEG1、SEG2,如图:

可以看到这种对齐方式在文件段的内部会有很多内部碎片,浪费磁盘空间,可执行文件总长度只有12014字节,却占了5个页。为了解决这个问题,UNIX系统采用了让那些个个段接壤的部分共用一个物理页面,将该物理页面映射两次,系统将它们映射两份到虚拟地址空间,其他的都按照正常的页粒度进行映射。

iOS8是基于iOS7进行升级 iOS8有许多的更新 (比如 连续性等) 所以会有占用 在下载完软件包时 实际占用达到 4GB 在完成更新后 iOS8软件包中的一些内容会自动删除(可能升级后占用1GB左右 之后苹果在下一次更新后 删除更多的不必要的内容) 因为更新必要的内容会替代某些iOS7的内容以及补充 如果您下载了新版iOS8的软件包 但是并不打算升级新版iOS8 您可以在 设置 通用 用量 中找到iOS8 点击它 并在它的页面中删除它 即可清除它所占的内存 如果您已经成功更新了 iOS系统会自动删除内容 来减少内存占用

-(float) cpu_usage

{

kern_return_t kr;

task_info_data_t tinfo;

mach_msg_type_number_t task_info_count;

task_info_count = TASK_INFO_MAX;

kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, task_info_count);

if (kr != KERN_SUCCESS) {

return -1;

}

task_basic_info_t basic_info;

thread_array_t thread_list;

mach_msg_type_number_t thread_count;

thread_info_data_t thinfo;

mach_msg_type_number_t thread_info_count;

thread_basic_info_t basic_info_th;

uint32_t stat_thread = 0; // Mach threads

basic_info = (task_basic_info_t)tinfo;

// get threads in the task

kr = task_threads(mach_task_self(), thread_list, thread_count);

if (kr != KERN_SUCCESS) {

return -1;

}

if (thread_count > 0)

stat_thread += thread_count;

long tot_sec = 0;

long tot_usec = 0;

float tot_cpu = 0;

int j;

for (j = 0; j < thread_count; j++)

{

thread_info_count = THREAD_INFO_MAX;

kr = thread_info(thread_list[j], THREAD_BASIC_INFO,

(thread_info_t)thinfo, thread_info_count);

if (kr != KERN_SUCCESS) {

return -1;

}

basic_info_th = (thread_basic_info_t)thinfo;

if (!(basic_info_th->flags TH_FLAGS_IDLE)) {

tot_sec = tot_sec + basic_info_th->user_timeseconds + basic_info_th->system_timeseconds;

tot_usec = tot_usec + basic_info_th->system_timemicroseconds + basic_info_th->system_timemicroseconds;

tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE 1000;

}

} // for each thread

kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count sizeof(thread_t));

assert(kr == KERN_SUCCESS);

return tot_cpu;

}

对于大多数APP来说,内存占用主要就是,本文将从实用角度分析,iOS的内存占用、测量、优化等。

在移动 *** 作系统设备中,是不能像PC一样进行内存swap的,而随着用户的使用,打开的应用越来越多,应用使用的内存也越来越多,当占用的内存达到某个临界值时,iOS系统会尝试按照优先级逐个kill掉应用程序,以维护系统的流畅和稳定。

当iOS系统在清理内存过程中,优先级到了前台正在运行的应用程序,那么就会出现前台应用程序闪退的现象,也就是通常所说的OOM。

实际上,对于iOS系统内存,根据划分的方法方式,有很多内存种类,比较常见的有clean memory, dirty memory,有virtual memory, resident memory,等等。那么这么多的内存,重点要关注什么呢?

也就是说,iOS内存优化看“memory footprint”,“memory footprint”优化看“Persistent Bytes for All Heap & Anonymous VM”

先打一个比喻,我们平时为了传输方便,往往会对文件进行压缩,得到一个rar或者zip的压缩包,当我们要阅读文件时,需要先解压压缩包,得到doc或者txt等文档,然后再打开阅读。

类似的,我们平时看到的jpg,png,就是上面所说的压缩包,这个文件是不能直接上屏渲染的,需要先解压缩,然后才能在上屏。而我们平时无感知,直接打开文件就能看,是因为解码渲染很快,在你点击的时候就完成了解码+渲染的 *** 作了,类似zip压缩包也可以不解压直接预览一样。

那么显而易见,我们看到的磁盘上的和最终渲染出来的是不同的,那么实际加载渲染时的内存要怎么算呢。在iOS中可以通过以下公式快速计算。其中4是每个像素占用的byte,在iOS中固定为4(至少目前为止是的),Android中需要根据实际的调整,一般也是4。

如果要进行内存的优化,首先得保证能监测到的内存大小。内存的测量,各家有各家的方案,但是总的来说,都是在某个或多个加载的入口,进行侵入或非侵入AOP,进行相关的计算。

这里推荐一个方法,实用NSHashtable,弱引用持有对象。将的对象放到这个弱引用的hash表中,可以实时查看当前仍存活的所有对象,并据此计算占用的内存。

iOS中UIImage内存占用:

iOS内存-内存优化

iOS内存优化,大的方向就是:

就是在页面中同时加载的数量要少,单张的大小要小,占用的内存要勤释放,用CPU换内存。

一个典型的优化就是,UITableView中,cell的reuse。单个cell的高度推荐小于1屏,cell要能够重用,列表滚动时,cell中的按需加载和释放。能够做到这些,一般的内存问题都能够很好的解决。

目前流行的加载,都会选取CDN,将原图进行初步的压缩,然后加载,但是这个更多的考虑的是服务的的性能,负载均衡等等,客户端的收益基本就只有流量一条。客户端内存的优化微乎其微。

根据上面说的内存解释,我们知道内存暴涨就是在对其解压缩时。如果看过iOS最流行的加载框架SDWebImage,和腾讯开源框架LKImageKit,可以发现LKImageKit有一个很精细的加载优化,就是在解码时,根据加载的view的frame,进行解码。这样就避免了一个很小的view,加载一张很大的,消耗大量内存的情况。

在SDWebImage中,要实现这个feature会有点麻烦。需要将上层调用的frame透传到最下面的解码部分,且需要做一些错误校验。

此外,需要注意的是,压缩率比较高的,在进行这种二次压缩时,压缩后的有可能会有很严重的失真。

2GB到4GB。

iOS系统163的内存占用大小取决设备,一般来说,iOS系统163的内存占用大小在2GB-4GB之间,具体大小可以在设备的设置中查看。

支持HomePod二代第一个主要升级,就是对HomePod二代的配对支持。

以上就是关于iOS内存的深入探究(WWDC 2018 session 416)全部的内容,包括:iOS内存的深入探究(WWDC 2018 session 416)、苹果手机怎么看照片大小、iOS 管理内存的方式 - 内存管理系统等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9442406.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存