zRAM内存压缩技术分析及优化方向

2023-05-16

目录

1. zRAM出现的背景

2. zRAM软件架构

3. zRAM实现分析

3.1 zRAM驱动模块

3.2 数据流模块

3.3 压缩算法模块

3.4 zRAM读写流程

3.5 zRAM writeback功能

4. zRAM性能调优

4.1 zram大小

4.2 内存压缩算法

4.3 zram的簇预读

4.4 zram的vma预读

4.5 zram使用程度倾向

4.6 zRAM去重

4.7 多种压缩算法组合压缩

5. 参考资料


1. zRAM出现的背景

阿姆达尔定律告诉我们,任何计算机操作系统总是存在瓶颈。从历史上看,许多系统上工作负载的瓶颈是 CPU,因此系统设计人员致力于 CPU 运行更快、更高效,不断增加 CPU 内核的数量。 慢慢地,RAM 越来越成为瓶颈。当数据从磁盘加载到 RAM时,CPU会闲置地等待。增大 RAM 并不总是一个具有成本效益的选择,有时甚至根本不是一个选择。更快的 I/O 总线和固态磁盘SSD减少了瓶颈,但并没有消除它。于是工程师们想,假如可以增加存储在 RAM 中的有效数据量,那不是很好吗?而且,由于这些 CPU 无论如何都在等待,也许我们可以使用这些空闲的 CPU 周期来做一些事情实现这一目标?这是内核压缩的目标:我们在 RAM 中保留更多压缩数据,并使用空闲的 CPU 周期来执行压缩和解压缩算法。

zRAM于2014 年进入 Linux 3.14 内核主线,但由于 Linux 用途十分广泛,这一技术并非没有默认启用,只有 Android 移动终端设备和少部分的 Linux 桌面发行版如 Fedora 默认启用了这一技术,以保证多任务场景下内存的合理分层存储。

举个具体的例子,你在android手机上连续打开了10个应用,系统空闲内存持续下降,通过zRAM内存压缩会把最近最少使用的页面压缩起来, 如淘宝的页面已最近最少使用的,原来占用100M的匿名页会压缩起来存放,压缩后占用40M,通过这个压缩就节省了60M内存。从而过到内存压缩保留更多数据在RAM中的目的, 让用户体验更佳。

2. zRAM软件架构

zRAM本质是一个块设备驱动,它使用内存模拟block device的做法。它把内存回收的策略交给内存管理,把压缩和解压缩交给压缩库,把自身内存分配交给zsmalloc, zRAM自身就是一个简单的驱动。

zRAM的软件架构主要包含3部分:

3. zRAM实现分析

3.1 zRAM驱动模块

  • zram_init

zram_init注册了zram块设备驱动,流程如下:

  • disksize_store

创建zram设备驱动后,通过用户态节点配置zram块设备大小, 对应disksize_store函数。

流程如下:

  • zram_make_request

所有zram的块设备请求都是通过zram_make_request进行的。

zram_make_request流程如下:

3.2 数据流模块

内核使用zcomp_strm结构描述压缩数据流,buffer用于存放压缩后的临时数据。

struct zcomp_strm {
	/* compression/decompression buffer */
	void *buffer;
	struct crypto_comp *tfm;
};

以前的3.15老版本内核提供了接口给上层设置最大压缩流。笔者从4.19内核中已经看到,尽管还是保留这个接口,但其实设置已经没有意义了,因为底层内核会针对各个CPU都配置一个压缩数据流。内核zram.txt有描述:

Set max number of compression streams Regardless the value passed to this attribute, ZRAM will always allocate multiple compression streams - one per online CPUs - thus allowing several concurrent compression operations. The number of allocated compression streams goes down when some of the CPUs become offline. There is no single-compression-stream mode anymore, unless you are running a UP system or has only 1 CPU online.

我们看下设置下来的值内核怎么处理,代码如下,它直接什么都不做,直接给返回了,所以新版本这里即便设置了也是设置了个寂寞,哈哈。

static ssize_t max_comp_streams_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t len)
{
	return len;
}

创建压缩数据流程如下:

之所以要针对每个在线CPU都创建一个压缩数据流,主要是优化系统中并发的情况。每个写压缩操作都独享一个压缩数据流,通过多个压缩数据流,使得系统允许多个并发压缩操作。

3.3 压缩算法模块

zRAM默认使用lzo压缩算法,但其实 zRAM 支持的压缩算法有很多,我们可以通过 cat /sys/block/zram0/comp_algorithm 获取支持的算法,当前启用的算法被[]括起来。

有人可能有疑问,zRAM使用哪种压缩算法最好?其实之所以同时存在这么多压缩算法是因是这些压缩算法并不存在绝对优劣, 各在优劣,有的压缩率高CPU消耗高、有的压缩率低CPU消耗低……, 在不同的硬件不同的场景也会有表现的差异,因此只有进行真实的测试,才能最合理地选择压缩算法。

工程师们也在持续优化压缩算法。截至当前,最新版本LZ v1.9.4(2022 年 8 月 16 日更新)在ARM64上最高解压缩性能优化了20%,最近的apple M1 芯片尤其如此,在 macbook 笔记本电脑和 nucs 中都有使用。

下面截取了几种算法在x86机器上的表现:

就上表而言, lz4压缩率与LZO很接近,但压缩和解压缩速度是远优于LZO压缩算法的,尤其是解压缩性能,是碾压性的。

近几年合入的zstd压缩算法,压缩率更高, 查压缩和解压缩会慢一些。

网上看到有大神写过脚本实测试过(这里就无耻地引用一下吧), 测试脚本[1]:

3.4 zRAM读写流程

zram最典型的操作就是读写行为, 下面针对读写流程进行分析。

  • 写(压缩)流程

  • 读(解压缩)流程

3.5 zRAM writeback功能

zRAM是将内存压缩后存放起来,仍然是在在RAM中。如果有大量一次性访问页面被压缩后很长时间没有被再次被访问, 虽然经过压缩但仍然占内存。zRAM支持设置外部存储分区作为zRAM的backing_dev,对不可压缩内存(ZRAM_HUGE)和长时间没有被访问过的内存(ZRAM_IDLE)回写到外部存储中。

以Android手机为例, 如果配置开启了zram writeback有idle回写功能,流程如下:

4. zRAM性能调优

zRAM提供了非常多的可配置选项,调优方式也多种多样。本文针对常见原生配置及社区最新进展做调优思路讨论,不涉及任何具体实施的建议及方案,也不一定完全适用于各生产环境。

4.1 zram大小

【调优节点】: /sys/block/zram0/disksize

内核提供了/sys/block/zram0/disksize节点供配置zram大小。可以实际使用场景实测,一般有场景、重载的场景zram等典型场景观察内存相关指标。根据需求配置合理的zram大小。有人可能问:" 反正这个是最大值,不是设置越大越好吗?”

我们在上面disksize_store分析的时候提到过,zram大小是需要为其分配zram table的,是需要占用一定内存空间的。如果配置很大的zram空间但平时有用不着,这个就浪费内存的。

4.2 内存压缩算法

【调优节点】:/sys/block/zram0/comp_algorithm

在上面讲解压缩算法的时候,我们提到过各种压缩算法,这些压缩算法在不同平台,不同场景都有差异性的表现。可以根据需求选择最适用的。评估的考量主要是压缩/解压缩消耗的CPU cycle和压缩率的平衡。

4.3 zram的簇预读

【调优节点】:/proc/sys/vm/page-cluster

page-cluster的作用就是每次从交换设备读取数据时多读 2^n 页,一些块设备或文件系统有簇的概念,读取数据也是按簇读取,假设内存页大小为 4KiB,page-cluster为3的情况每次读取的一簇数据为 32KiB

这是swap时利用局部性原理,把附近的几个页“顺便”也读出来,减少频繁读取磁盘的次数。而其实使用zRAM时,并不会有磁盘相关操作,这里多读一些甚至是浪费内存的。

而且压缩后在zram中的数据也并不一定具有局部性原理。这里是可以通过实际测试来判断的。

void __init swap_setup(void)
{
	unsigned long megs = totalram_pages >> (20 - PAGE_SHIFT);

	/* Use a smaller cluster for small-memory machines */
	if (megs < 16)
		page_cluster = 2;
	else
		page_cluster = 3;
	/*
	 * Right now other parts of the system means that we
	 * _really_ don't want to cluster much more
	 */
}

以这份[2]提供的测试数据来看,对zRAM设备把page_cluster调小,平均延迟是改善了。

4.4 zram的vma预读

【调优节点】:/sys/kernel/mm/swap/vma_ra_enabled

预读始终是swap机制的优化方向之一。上面提到的基于page-cluster的预读可能不一定适合zram。内核工程师们提出了基于VMA地址的预读, 对于zRAM可能更符合局部性原理。

内核支持可配置基于vma的预读还是page-cluster的预读。

struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
				struct vm_fault *vmf)
{
	return swap_use_vma_readahead() ?
			swap_vma_readahead(entry, gfp_mask, vmf) :
			swap_cluster_readahead(entry, gfp_mask, vmf);

社区描述[3]的测试结果会有明显效果:

4.5 zram使用程度倾向

【调优节点】:/proc/sys/vm/swappiness

swappiness参数用于表征更倾向于回收匿名页还是文件页。Linux5.8以下版本swapiness默认值是60,最大值是100, 如果swappiness设置为100表示匿名页和文件将用同样的优先级进行回收。由于zram设备非外部存储设备,其本质还是对RAM的访问,可以相对更激进地使用zram,即把swappiness设置得比100还大,也就是回收匿名页比文件页激进。

linux5.8支持把swappiness设置得比100还大, 最大值从100修改为了200, 提交[4]已经进入5.8版本主线。如下:

mm: allow swappiness that prefers reclaiming anon over the file workingset

文档同时也更新了说明, 对于zram设备建议swappiness大于100。

For in-memory swap, like zram or zswap, [...] values beyond 100 can be considered. For example, if the random IO against the swap device is on average 2x faster than IO from the filesystem, swappiness should be 133 (x + 2x = 200, 2x = 133.33).

4.6 zRAM去重

【调优节点】:/sys/block/zram0/ dedup_enable

Android 是使用 zram 作为swap device的最大用户之一,节省zram内存使用量非常重要。有研究论文《MemScope: Analyzing Memory Duplication on Android Systems》[5]表明Android的内存内容的重复率是相当高的。

Android 应用进程和系统进程可能表现出不同的特点,因为 Android 应用程序运行 dalvik VM 但非应用程序进程不运行。应用进程的内存内容重复率平均约14%,系统进程的内存内容重复率平均约3%。

论文调查了哪些内存区域包含最多重复页面,结果是超过 80% 的重复页面来自来自匿名页、gralloc-buffer、dalvik-heap、dalvik-zygote和 libdvm.so 库的 BSS 段。如下图:

于是内核工程师们提出了zram支持去重功能以节省功能,提交集[6]如下:

zram: implement deduplication in zram

可以通过/sys/block/zram<id>/io_stat/中zram->dedup->dedups查看重复的page量。

4.7 多种压缩算法组合压缩

社区在讨论一个zram多重压缩的优化。可以在压缩后再次变更压缩算法对idle和huge的page再次压缩。基本思想是使用一种更快但压缩率较低的默认算法率和可以使用更高压缩率的辅助算法。以较慢的压缩/解压缩为代价。替代压缩算法可以提供更好的压缩比,以减少 zsmalloc 内存使用。当然这个改动[7]还没有合入到主线中。

zram: Support multiple compression streams

5. 参考资料

https://lwn.net/Articles/545244/

https://segmentfault.com/a/1190000041578292

https://tjtech.me/analyze-zram-stream-operation.html

http://kernel.meizu.com/zram-introduction.html

https://www.dazhuanlan.com/songlipeng2003/topics/1069737

https://github.com/lz4/lz4/releases

https://blog.csdn.net/Death__Azreal/article/details/118601258

https://docs.kernel.org/admin-guide/sysctl/vm.html

https://lore.kernel.org/linux-mm/20170915034209.GA9690@bbox/t/

https://dl.acm.org/doi/10.1145/2797022.2797023

https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1434699.html

参考

  1. ^https://gist.github.com/LuRenJiasWorld/7de95bbfdba542cea17271ba06ccb85a
  2. ^linux - 配置 ZRAM,实现 Linux 下的内存压缩,零成本低开销获得成倍内存扩增_个人文章 - SegmentFault 思否
  3. ^[PATCH -mm -v4 0/5] mm, swap: VMA based swap readahead
  4. ^kernel/git/next/linux-next.git - The linux-next integration testing tree
  5. ^MemScope | Proceedings of the 6th Asia-Pacific Workshop on Systems
  6. ^[PATCH v5 2/4] zram: implement deduplication in zram - js1304
  7. ^[PATCH RFC 0/7] zram: Support multiple compression streams
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

zRAM内存压缩技术分析及优化方向 的相关文章

  • 快速幂和矩阵快速幂

    快速幂 快速幂是数论中最简单的几种算法之一 xff0c 顾名思义 xff0c 就是快速计算某个数的多少次幂 相较于传统循环pow的计算方法 xff0c 快速幂的复杂度为 O l o g 2
  • ucosii中消息队列、消息邮箱、信号量的区别

    1 用信号量进行行为同步时 xff0c 只能提供同步的时刻信息 xff0c 不能提供内容信息 若被控制方要求得到控制方的内容信息时 xff0c 可以使用消息邮箱或消息队列 2 但由于消息邮箱里只能存放一条消息 xff0c 所以使用消息邮箱进
  • 项目时间管理的几种方法

    随着项目活动分解的深入和细化 xff0c 工作分解结构 WBS 可能会需要修改 xff0c 这也会影响项目的其他部分 例如成本估算 xff0c 在更详尽地考虑了活动后 xff0c 成本可能会有所增加 xff0c 因此完成活动定义后 xff0
  • 【内网学习笔记】25、Exchange 邮件服务器

    1 Exchange 的基本操作 在 Exchange 服务器上的 PowerShell 里进行以下操作 将 Exchange 管理单元添加到当前会话中 add pssnapin microsoft exchange 查看邮件数据库 Get
  • cuda.tensor转为numpy, 以及numpy与tensor互相转换

    1 cuda tensor转为numpy 解决 TypeError can 39 t convert cuda 0 device type tensor to numpy Use Tensor cpu to copy the tensor
  • [软件工程]第三章 结构化方法————(2020.6.11学习笔记)

    目录 1 xff0c 第一节 结构化需求分析 2 xff0c 第二节 结构化设计 第一节 结构化需求分析 需求分析面临的挑战 xff08 1 xff09 问题空间理解 xff08 2 xff09 人与人之间的通信 xff0c 有效沟通 xf
  • ESP8266系列WIFI模块的使用·

    一 概述 ESP8266是由乐鑫公司出品的一款物联网芯片 xff0c 因为价格较低 xff0c 性能稳定等收到很大关注 该芯片可工作于三种种模式下 xff0c 分别是 xff1a AP模式 xff0c station模式以及混合模式 xff
  • idea中使用actiBPM

    在idea中actiBPM插件的支持不是太友好 xff0c 顺便附上插件下载地址 链接 xff1a https pan baidu com s 1cyaDGDXWtJuWys3WVG98qA 提取码 xff1a onuz 因此在这里记录一下
  • 动态规划、贪心算法、分治算法的优缺点分析

    动态规划模型相对于静态规划模型的优点 xff1a 1 能够得到全局最优解 xff1b 2 可以得到一族最优解 xff1b 3 由于动态规划方法反映了动态过程演变的联系和特征 xff0c 在计算时可以利用实际知识和经验提高求解效率 动态规划模
  • 如何在vscode上运行调试C++(最简单的方法)

    Visual Studio Code vscode同样是微软出品的 支持 看上面的vside介绍吧 就省略了 人称宇宙第一编辑器 作为编辑器 它几乎支持所有的语言 对应语言风格的高亮 自动缩进 代码纠错 代码提示和代码补全等 要是有相应的编
  • visual studio中,已经安装完成后如何再安装其他组件(即在安装过程中未勾选的)怎么办?

    方法一 xff1a 控制面板 gt 程序 程序和功能 右键visual studio 单击更改 下面有三个按钮 单击更改 xff0c 把需要安装的组件全钩 xff0c 然后点击更改即可 1 在win10界面左下角搜索 控制面板 2 寻找程序
  • Unity can't be installed on this disk.The contents of this disk can't be changed.

    1 问题 在使用mac下Unity的时候 xff0c 通常情况下我们的方法都是通过Hub的安装按钮下载 但是 xff0c 很多时候上面并没有我们需要的版本 于是我们傻乎乎的通过点击上面的 xff1a 官方发布网站 进行下载 在下载的第五个步
  • Unity之【使用Blend-Tree】

    Blended Tree 材料准备创建Animator创建Controller配置混合树脚本代码效果演示 材料准备 人物模型和动画 直接去Unity素材库里找 xff0c 动画可以找可以自己录制 Unity编辑器 创建Animator 步骤
  • 【GIT】git个人笔记

    GIT个人手册 版本 日期 修订内容 作者 V01 2019 06 25 初稿 备注 xff1a 使用中不断迭代完善 xff0c 其他人使用中有其他总结的 xff0c 可以补充 目录 第一章 说明 一 1 1 GIT 中文手册 一 1 2
  • linux常用开关机指令

    关机命令 xff1a shutdown h now xff08 立刻进行关机 xff09 halt xff08 立刻进行关机 xff09 poweroff xff08 立刻进行关机 xff09 重启命令 xff1a shutdown r n
  • _vimrc (linux版)

    一般放在 xff1a etc vim span class token string 34 vimrc 34 span span class token function vim span config span class token f
  • 01_Unity事件函数OnMouseDown生效条件

    前言 Unity提供了OnMouseDown xff0c OnMouseEnter xff0c OnMouseExit等方法 xff0c 这些方法可以很方便的帮助我们处理鼠标的时间响应 但是需要注意他的生效条件 xff0c 最近我在制作视频
  • 算法题型:滑动窗口(leetcode 209)

    一 209 长度最小的子数组 难度中等 题目描述 给定一个含有 n 个正整数的数组和一个正整数 s xff0c 找出该数组中满足其和 s 的长度最小的连续子数组 如果不存在符合条件的连续子数组 xff0c 返回 0 示例 输入 s 61 7
  • 前端:bootstrap table表格属性、列属性、事件、方法

    目录 一 使用前提 二 基本属性 列参数 事件 方法 多语言 一 使用前提 1 在html中引用table相应的包 lt link rel 61 34 stylesheet 34 type 61 34 text css 34 href 61
  • Git学习(一):Git介绍、仓库和分支等基本概念解释

    目录 一 Git介绍 二 关于git仓库和分支的解释 1 仓库 2 分支 3 例子解释 4 本地与远程建立联系 5 git merge命令解释 6 Merge Request解释 7 尽量避免冲突的做法 8 Upstream概念及使用 9

随机推荐

  • Ubuntu 解决wps缺乏字体

    文章目录 Ubuntu 解决wps缺乏字体 Ubuntu 解决wps缺乏字体 移植windows字体 xff1a 复制 C Windows Fonts 下的字体 到 usr share fonts truetype windows font
  • TensorFlow2安装(超详细步骤-人工智能实践)

    TensorFlow2安装教程 1 前言1 1 版本记录1 2 工具简介 2 详细步骤及安装语句2 1 安装Anaconda2 2 TensoFlow安装2 3 验证是否成功2 4 PyCharm下载与安装2 5 PyCharm环境配置2
  • 图像识别-数据清洗

    1 删除不清晰的图片 xff08 由于图片是从视频里截取到的 xff0c 摄像头在移动的过程中 xff0c 会出现自动对焦 xff09 模糊图片示例 xff1a 2 删除重复度高的图片 xff08 相似度高的图片 xff0c 无法给模型提供
  • 【Linux】nm命令|查看动态库包含的函数符号

    目录 0 前言 1 nm简介 2 nm命令用法和参数说明 3 nm用法和结果说明 4 nm 提示 no symbol 的问题 xff08 strip xff09 0 前言 下文1 3 摘抄自 xff1a Linux nm命令详解 https
  • Xmanager 5远程连接CentOS7图形化界面

    1 安装Xmanager 5 下载链接 xff1a https pan baidu com s 1JwBk3UB4ErIDheivKv4 NA 提取码 xff1a cw04 双击xmgr5 wm exe进行安装 点击 下一步 选择 我接受许
  • ROS遇到问题:rosdep找不到

    当在catkin工作区创建好了包以后 xff0c 要rospack depends1 beginner tutorials xff0c 出现了以下的提示错误 xff1a rospack Error the rosdep view is em
  • 纯JavaScript实现一个带cookie的学生管理系统

    由来 之前写过一个Jsp amp Servlet版本的学生管理系统 发出来之后 xff0c 有一个网友找我给他写JavaScript版本的 xff0c 时间也过去很久了 xff0c 我估摸着他那门课已经结束了 xff0c 所以整理了一下代码
  • FreeRTOS互斥信号量与二值信号量使用时的区别

    1 互斥信号量 互斥信号量的申请与释放是要在同一个任务中进行的 xff0c 不能在一个任务中申请而在另一个任务中释放 互斥信号量主要解决的是 xff0c 我在用的时候 xff0c 别人都不能用 举个例子 xff0c 我在像一段内存中写数据的
  • 小白入门photoscan

    1 安装 我装的是photoscanPro 1 4 5版本 注 xff1a 刚开始是在官网上下载的 xff0c 要收费就点了试用 xff0c 结果当我等了一天把将近200张图片处理完后 xff0c 告诉我试用版不能保存文件 绝望 所以要是像
  • matlab学习(1)strsplit与strtok

    strsplit函数用法 xff1a lt 1 gt 默认使用空格符分割 返回一个cell数组 lt 2 gt 也可以指定第二个参数进行分割 lt 3 gt 第二个参数也可以时包含多个分隔符的元胞数组 lt 4 gt strsplit还可以
  • latex之注释快捷键

    注释快捷键 ctrl 43 T 注释掉选中区域 ctrl U 解除选中区域的注释
  • Ceres-solver安装(win10+vs2015)

    Ceres solver安装 Vs2015 43 win10 文件已经上传至 永久有效 网盘 xff1a https pan baidu com s 1Vj n2Nbp9WFVlbjuXV OxQ 密码 xff1a 3rvo 1 将网盘里的
  • 关于Intellij IDEA的pom.xml添加依赖后仍找不到

    1 在pom xml中添加了junit依赖 也执行了项目 gt reimport xff0c 在本地仓库也确实存在junit依赖包 xff0c 打开里面的jar包也确实有Test class After class等文件 但是编译时仍然说找
  • 【Dll调试】DLL调试方法

    dll本身是没法运行的 xff0c 必须在其它工程调用dll时候才会运行 所以 xff0c 调试dll首先要将调用dll的工程和dll工程联系起来 解决方案中添加dll工程 xff1a 现在dll 和 应用程序两个工程就都在一个解决方案里了
  • 【原创】linux下将Python命令默认指向为Python3

    linux下输入Python命令默认指向的是 usr bin python 因此 xff0c 为了方便使用 xff0c 安装了python3后 xff0c 我们一般会创建软链接使 usr bin python指向 usr bin pytho
  • C#开发窗体程序全过程(项目目录、格式、控件使用、文件读写)

    目录 第一章 xff1a WinForm基础 一 概述二 在VS中新建窗体程序三 窗体 xff08 Form xff09 第二章 xff08 上 xff09 xff1a 控件与窗体 一 文本编辑控件二 图片框 xff1a PictureBo
  • JAVA面试题大全(200+道题目)

    目录 一 Java 基础 1 JDK 和 JRE 有什么区别 xff1f 2 61 61 和 equals 的区别是什么 xff1f 3 两个对象的 hashCode 相同 xff0c 则 equals 也一定为 true xff0c 对吗
  • 【Audio】查看手机的声卡信息

    以我的旧手机华为P8青春版为例 xff0c 我没有root xff0c 所以权限有限 找到开发者选项 在设置中找到开发者选项 xff0c 然后打开usb调试 下载adb工具 这个网上有很多 xff0c 可以自行下载 xff0c 主要包含如下
  • Jetson TX2 ubuntu18设置VNC时DesktopSharing打不开

    Jetson TX2设置VNC时DesktopSharing打不开 1 1 编辑 org gnome Vino 来加入缺失的 enabled 参数 sudo gedit usr share glib 2 0 schemas org gnom
  • zRAM内存压缩技术分析及优化方向

    目录 1 zRAM出现的背景 2 zRAM软件架构 3 zRAM实现分析 3 1 zRAM驱动模块 3 2 数据流模块 3 3 压缩算法模块 3 4 zRAM读写流程 3 5 zRAM writeback功能 4 zRAM性能调优 4 1