1、ZRAM那点事那点事ZRAM和和ZSMALLOC简介及简介及3个问题的改进和个问题的改进和1个提高个提高什么是ZRAM?Linux内核中提供的虚拟磁盘。将写入的页面压缩并分配内存存储在系统中。主要用来作为SWAP设备。常用在用闪存作为存储空间的设备上。为什么用ZRAM?(见下图)设备上可以不再需要开其他的SWAP。(区别于ZSWAP)节省了闪存的寿命。节省了硬盘空间。节省了BLOCK IO。通过压缩节省内存。Android下可用来提高进程保活度。LRU ShrinkerZRAMAndroid 无SWAPAndroid有SWAP什么是ZSMALLOC?(见下图)针对内存压缩场景设计的内存分配器。
2、类似其的还有ZBUD和Z3FOLD。ZRAM直接使用ZSMALLOC。ZSWAP通过ZPOOL框架使用其。ZSMALLOC内部结构(见下图)基本结构:每个对ZSMALLOC的使用者会申请一个zs_pool。每个zs_pool根据存储数据的大小分出若干size_class。每个size_class中根据元素占有状态分出4个fullness_list。每个fullness_list保存若干zspage,每个zspage由一个到几个几个不连续page组成。每个zspage(由最多4个非连续page组成)保存若干储存对象obj,ZRAM中每个page最终会被保存为一个obj。ZRAM通过handle以
3、映射的形式访问某个obj,因为是映射式的访问,highzone page也是可以使用的。(今年还有修改,后面会提到)比较重要:页面被压缩后存储为一个obj,被存于由页面组成的zspage中,外面访问其要通过handle。实际观测ZSMALLOC内部结构可在配置内核中打开CONFIG_ZSMALLOC_STAT=y。访问/sys/kernel/debug/zsmalloc/zram0/classes就可查看ZSMALLOC中的内部信息。注意查找彩蛋ZRAM使用中出现3大问题Minchan Kim于2015年提出:外部碎片 不能移动的页 内部碎片这三个问题有一定相关性,并且都需要在ZSMALLOC
4、中进行修复。从去年开始层层修复到今年在Upstream上全部修复完成。内部碎片(见下图)开ZRAM时间长了以后感觉内存还是不够。杀掉一堆进程后又感觉好点了。但是很快又不够了。内部碎片的成因(见下图)针对一个尺寸的size_class中实际存储数据的是obj。而obj被存储在zspage中,随着使用会不断有分配和释放,如果没有相应碎片处理,则会出现很多碎片化的zspage。内部碎片导致ZRAM内存使用率变差,影响ZRAM效果。注意这张图和前面的图不同,因为前面的图是根据修正后来做的。fullness_list最早的抗碎页机制(见下图)ZS_EMPTY,ZS_ALMOST_EMPTY,ZS_ALM
5、OST_FULL,ZS_FULL这4个zspage的列表。每个列表储存的ZSPAGE是其标记的所处状况。使用的时候优先从ZS_ALMOST_FULL中找ZSPAGE。缺点:完全被动,虽然分配抗碎页,但是释放还是碎片化的。_zs_compact主动碎片清理(1)准备工作(见下图)将handle从存储指向obj的数据改为指向obj的指针。这样zsmalloc内部可以根据obj位置的变化修改handle内容,ZRAM还可以找到某个页面对应的obj。_zs_compact主动碎片清理(2)实际处理(见下图)对一个size_class进行如下处理:按照先ZS_ALMOST_EMPTY,后ZS_ALMOS
6、T_FULL的顺序抽出一个来源zspage。然后按照先ZS_ALMOST_FULL,后ZS_ALMOST_EMPTY的顺序抽出一个目标zspage。把来源zspage中的obj依次移动到目标zspage中。将已经空了的来源zspage释放掉,再按照刚才的方法取得一个来源zspage。将满了的目标zspage加入ZS_FULL,再按照刚才的方法取得一个目标zspage。如此循环,直到无法取得来源zspage或者目标zspage。_zs_compact主动碎片清理(3)调用处理(见下图)zs_compact会依次调用_zs_compact对一个zs_pool中的每个size_class进行清理。需
7、要的时候可通过sysfs接口调用清理。或者shrink_slab会调用zs_shrink,zs_shrink会调用zs_compact根据需要需要做清理。内部碎片问题的相关PATC H相关的PATCH主要集中在zsmalloc.c,集成难度不大,建议内核不是很老的系统遇到相关问题可以打上尝试一下。另外注意在今年有一个关于handle写保护的修复务必打上。外部碎片和 不可移动页面(见下图)因为一个设计引起的问题,所以放在一起介绍。深度使用ZRAM后的现象:1.系统经常遇到连续页面分配失败的报错。2.系统可移动页块变少,不可移动页块变越来越多。3.因为页面碎片增加引起的系统变慢。4.在打上各种主动
8、使用CMA相关的PATCH后(具体可见到2014年在CLK上关于CMA的演讲),ZRAM中存放比较多内存后,还会遇到CMA页面剩下很多,普通内存剩下很少的情况。外部碎片和不可移动页面的成因(见下图)ZSMALLOC分配的页面为不可移动页面。被放入ZRAM的LRU页面(可移动)变成不可移动页面,这些页面不能被LINUX内核系统的除碎页功能处理,导致系统页面碎片化严重。导致了现象1,2,3。CMA页面不能被当成不可移动页面分配(原理同样见我2014年在CLK的演讲),导致了现象4。题外话:碎片问题在A64上被放大因为A64的THREAD_SIZE比A32大。除ZSMALLOC外,去年到今年还有若干
9、相关提高。外部碎页解决方案:Non-LRU pagemigration(见下图)没有条件就创造条件,不能移动就让它能移动。在ZSMALLOC内部,handle已经在前面处理好可以保证obj迁移到其他页面,处理掉之前保存在page结构里面的ZSMALLOC相关信息,实现了相关接口就令ZSMALLOC中使用的页可迁移了。外部碎页问题的相关PATC H因为要对页面移动相关代码进行修改,涉及到不少Linux内存管理相关代码,有一定难度。依赖内部碎页的相关修正patch。问题都解决完了再次查找彩蛋ZRAM的低压缩率问题 这是我看到的一个比较极端的例子,ZRAM中70%的页面起到的压缩作用是0。实际情况可
10、能没有这么糟糕,另外CONFIG_ZSMALLOC_STAT选择默认不打开,所以一般人可以做到眼不见心不烦。这样的PAGE浪费了CPU的时间,浪费了ZRAM空间。这时勉强能起到的作用只有把非HIGHMEM ZONE的页面保存到HIGHMEM ZONE上,在一定程度上节省了非HIGHMEM ZONE。但是64位时代到来,使用HIGHMEM减少,优势不再明显。ZRAM的本质,提高思路的来源(见下图)用CPU和少量内存换取系统BLOCK IO和比较多数量内存。存放到ZRAM中的页面压缩率越好,ZRAM的工作效果越好。但是现在不能选择,只能照单全收。Android有SWAPNon-Swap(见下图)为
11、了提高ZRAM压缩率。其思路是把压缩率不高的页面不写入ZRAM,同时将其从LRU列表中抽出去放到单独的页列表保证其不会再次被写入ZRAM。当这些页面再次被写时,表明其有可能在压缩率上出现变化,将其再次放回LRU列表。Non-Swap的实现(见下图)根据设置放弃在ZRAM中存储压缩率不高的页。具体步骤:shrink_page_list在发送PAGE到ZRAM之前把UNMAP PAGE改为把页面设置为只读。把页面发给ZRAM。ZRAM压缩页面,然后检查压缩率,压缩率不足的页面设置NON-SWAP标志。返回shrink_page_list,把没有NON-SWAP也没有在发送到ZRAM过程中被写入的页
12、面UNMAP然后释放掉。把被设置为NON-SWAP的页面丢入UNEVICTABLE列表防止再次被shrink_page_list。一直到这个页面被写触发handle_pte_fault,在这里去掉NON-SWAP标志并踢回LRU PAGE列表。https:/lkml.org/lkml/2016/8/22/151Non-Swap的效果(见下图)一个平台用内部稳定性测试。未打上Non-Swap功能PATC H和打开Non-Swap功能后对比结果,每次的LMK次数都降低50%以上。最好的一次降低了79%。能达到这点的原因我分析是因为当压缩率提高时,每做一组页面shrink都可以获得比低压缩率更高的内存释放。另外就是在考虑如何处理Non-Swap页面的时候,想到了如何让系统支持任意多的watchpoint。不过超过本话题讨论范畴了。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。