Linux内存管理(20)--ZRAM

作者 by adtxl / 2022-03-01 / 1 评论 / 693 个足迹

版权声明:本文为CSDN博主「Felix.Ma」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mafei852213034/article/details/106444109

1.ZRAM

1.1 zram的理解

ZRAM(压缩内存)的意思是说在内存中开辟一块区域压缩数据……就是说假设原来150MB的可用内存现在可以放下180MB的东西……本身不会提高内存容量和运行速度……只是让后台程序更少被系统砍掉罢了,为了能得到更多多任务运行……而且这个压缩动作会加重CPU负担……

ZRAM是linux的一种内存优化技术,基本工作原理是:通过划定一片区域,将压缩过后的硬盘数据放入该区域,以实现高速读取。

  • ZRAM是内存压缩,所有写入内存的东西都会经过压缩,会少量增加CPU负担
  • SWAP是交换分区,类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况
  • ZRAM是把RAM划分一部分出来作为SWAP使用,存储的是压缩过的内容(不然就毫无意义了),
  • SWAP是把flash划分一部分出来作为SWAP使用。
  • ZRAM是一个Linux内核驱动,ZRAM大体上可以看成是用内存做一块虚拟盘,拿来作为Linux的交换分区。和普通的ramdisk不同,ZRAM对存放的内容会进行实时的压缩,以提高实际的容量。
  • 利用ZRAM并不是减小Android的内存占用,而是通过zRAM来提供交换空间,从而在内存紧张时释放出更多的可用内存,同时又避免传统的交换到文件系统的开销。
  • ZRAM可以分出一块内存,然后让系统当作虚拟内存来使用。传统的虚拟内存是存放在磁盘上的,而ZRAM存在内存里,并会进行压缩。这样的虚拟内存访问速度可以提高很多,内存利用率也会大幅提高。所以对于小内存设备,比如512M内存的Android设备,或者1G内存的电脑,都会有很大帮助。应该和OS X 10.9的内存压缩效果差不多,而且设计得更为巧妙。在CPU有较快速度的年代里,利用CPU的资源对内存进行压缩,以便在小内存设备里也能存下更多的后台进程,是个很不错的方法。

1.2.zram swap内存管理讲解

1.2.1 Android内存管理机制

假设你先开了QQ,然后跟A聊天,然后你按了HOME键,又开了微信和B聊天,假设这时候系统基本没有内存了,又按了HOME键想打开UC看看微博。Android会怎么干哪?他发现QQ最先到后台,就把QQ给干掉了。玩了会UC,你又要跟A聊天,这时候android发现又没有内存了,发现微信半天没用了,就把微信给干掉,然后给QQ用。问题来了,你本来想多任务,结果只能同时用两个程序,打开第三个如果内存不够就要干掉之前的。但是你期望的是我如果没有把他退出去,我希望下次再打开QQ的时候还是在给A聊天的界面。

1.2.2 ZARM SWAP解决方案:

SWAP最开始的方案就是专门从flash(闪存ROM)上分出一块区域,每次如果内存(运行存储RAM)不够不是吧程序给干掉,而是把程序占用内存的数据复制到SWAP分区,等切换回来的时候就直接把这部分复制到内存里,这样程序直接就恢复到之前的状态,譬如QQ上与妹纸A聊天的界面。这样你就感觉程序还是以前的样子,没有被系统干掉。但是flash寿命有限一般10w次左右,这样频繁读写很快flash就挂了。于是攻城狮就想到了另外一个办法,把内存划分一部分拿出来当SWAP用,但是羊毛出在羊身上,原来你QQ占用50M内存,你又把他复制到SWAP里面还是50M,SWAP还是占用的内从,等于说一点都没减少内从使用,所以就有了ZRAM SWAP。攻城狮怎么干的呢?比如你QQ占用50M内存,他把他压缩到20M然后再放到SWAP里面,这样SWAP里面机可以放更多不用的程序,就可以释放更多的内存给新的程序用,于是你就发现多任务切换终于利索了。这就是 ZRAM SWAP.

举例说明

总内存:600M= 300M(SWAP) +300 (活动内存)

每个程序占用30M,压缩后是10M。

  • 没有ZRAM SWAP 方案:

你可以同时打开 20 个程序 600/30 = 20

  • 有ZRAM SWAP方案:

SWAP 里面可以保存 300/10 = 30

活动内存里可以运行 300/30 = 10

总共你可以同时运行 40 个程序, 这就是差别。

ZARM SWAP优点:

  • 可以让小内存的设备在多任务的情况下切换自如,提高用户体验。
  • zram把压缩的page直接交换到内存中,速度远远快于io操作。

ZARM SWAP缺点:

  • 如果在大内存的设备上使用,不仅不会快,反倒因为不断复制内存并且CPU反复压缩解压内存而拖慢速度。
  • 往往只有低端设备才会使用zram技术。
  • cpu就可能是单核心或性能低,压缩/解压会占用cpu时间,影响性能。
  • 内存小还要再开一块交换区,也增加了负担。

1.3.安卓手机有必要开zram吗?

如果你的可用运行内存实在是太小,且CPU性能不是太低端(zRAM会消耗CPU资源),那么zRAM还是有必要开。

2.SWAP解读

2.1 什么是SWAP,到底是干嘛的?

从功能上讲,交换分区主要是在内存不够用的时候,将部分内存上的数据交换到swap空间上,以便让系统不会因内存不够用而导致oom或者更致命的情况出现。

所以,当内存使用存在压力,开始触发内存回收的行为时,就可能会使用swap空间。

内核对swap的使用实际上是跟内存回收行为紧密结合的。

2.1.1 为什么要进行内存回收

内核之所以要进行内存回收,主要原因有两个:

  1. 内核需要为任何时刻突发到来的内存申请提供足够的内存。所以一般情况下保证有足够的free空间对于内核来说是必要的。另外,Linux内核使用cache的策略虽然是不用白不用,内核会使用内存中的page cache对部分文件进行缓存,以便提升文件的读写效率。所以内核有必要设计一个周期性回收内存的机制,以便cache的使用和其他相关内存的使用不至于让系统的剩余内存长期处于很少的状态。

  2. 当真的有大于空闲内存的申请到来的时候,会触发强制内存回收。所以,内核在应对这两类回收的需求下,分别实现了两种不同的机制:

    • 一个是使用 kswapd进程对内存进行周期检查 ,以保证平常状态下剩余内存尽可能够用。
    • 另一个是 直接内存回收(direct page reclaim) ,就是当内存分配时没有空闲内存可以满足要求时,触发直接内存回收。

这两种内存回收的触发路径不同:

  • 一个是由内核进程kswapd直接调用内存回收的逻辑进行内存回收;
  • 另一个是内存申请的时候进入slow path的内存申请逻辑进行回收。

这两个方法中实际进行内存回收的过程殊途同归,最终都是 调用shrink_zone() 方法进行针对每个zone的内存页缩减。

2.2 swappiness到底是用来调节什么的?

很多人应该都知道 /proc/sys/vm/swappiness 这个文件,是个可以用来调整跟swap相关的参数。这个文件的默认值是60,可以的取值范围是0-100。

这很容易给大家一个暗示:我是个百分比哦!

这个文件的值用来定义内核使用swap的积极程度:

值越高,内核就会越积极的使用swap;

值越低,就会降低对swap的使用积极性。

如果这个值为0,那么内存在free和file-backed使用的页面总量小于高水位标记(high water mark)之前,不会发生交换。

2.3 kswapd什么时候会进行swap操作?

我们回到kswapd周期检查和直接内存回收的两种内存回收机制。

直接内存回收比较好理解,当申请的内存大于剩余内存的时候,就会触发直接回收。

那么kswapd进程在周期检查的时候触发回收的条件是什么呢?

还是从设计角度来看,kswapd进程要周期对内存进行检测,达到一定阈值的时候开始进行内存回收。

这个所谓的阈值可以理解为内存目前的使用压力,就是说,虽然我们还有剩余内存,但是当剩余内存比较小的时候,就是内存压力较大的时候,就应该开始试图回收些内存了,这样才能保证系统尽可能的有足够的内存给突发的内存申请所使用。

2.4、什么是内存水位标记?(watermark)

那么如何描述内存使用的压力呢?

Linux内核使用水位标记(watermark)的概念来描述这个压力情况。

Linux为内存的使用设置了三种内存水位标记:high、low、min。他们 所标记的含义分别为:

剩余内存在high以上表示内存剩余较多,目前内存使用压力不大;

high-low的范围表示目前剩余内存存在一定压力;

low-min表示内存开始有较大使用压力,剩余内存不多了;

min是最小的水位标记,当剩余内存达到这个状态时,就说明内存面临很大压力。

小于min这部分内存,内核是保留给特定情况下使用的,一般不会分配。

内存回收行为就是基于剩余内存的水位标记进行决策的:

  • 当系统剩余内存低于watermark[low]的时候,内核的kswapd开始起作用,进行内存回收。直到剩余内存达到watermark[high]的时候停止。
  • 如果内存消耗导致剩余内存达到了或超过了watermark[min]时,就会触发直接回收(direct reclaim)。

那么watermark相关值是如何计算的呢?

所有的内存watermark标记都是根据当前内存总大小和一个可调参数进行运算得来的,这个参数是:/proc/sys/vm/min_free_kbyte

QA:

1.一个内存剩余还比较大的系统中,是否有可能使用swap?

有可能,如果运行中的某个阶段出发了这个条件zonefile+zonefree<=high_wmark_pages(zone),就可能会swap。

2.swappiness设置为0就相当于关闭swap么?

不是的,关闭swap要使用swapoff命令。swappiness只是在内存发生回收操作的时候用来平衡cache回收和swap交换的一个参数,调整为0意味着,尽量通过清缓存来回收内存。

3.swappiness设置为100代表系统会尽量少用剩余内存而多使用swap么?

不是的,这个值设置为100表示内存发生回收时,从cache回收内存和swap交换的优先级一样。就是说,如果目前需求100M内存,那么较大机率会从cache中清除50M内存,再将匿名页换出50M,把回收到的内存给应用程序使用。但是这还要看cache中是否能有空间,以及swap是否可以交换50m。内核只是试图对它们平衡一些而已。

4.kswapd进程什么时候开始内存回收?

kswapd根据内存水位标记决定是否开始回收内存,如果标记达到low就开始回收,回收到剩余内存达到high标记为止。

5.如何查看当前系统的内存水位标记?

cat /proc/zoneinfo

独特见解

 评论 1 条