PHP 无法直接使用或感知 zswap,因其属内核交换子系统,对用户态进程完全透明;开发者应优化 PHP 内存使用并合理配置内核参数如 vm.zswap.enabled、vm.swappiness 等。

PHP 本身不支持、也不能直接利用 zswap 或任何内核级硬件内存压缩功能。 这不是配置问题,而是架构层级的根本错位:zswap 是 Linux 内核的交换子系统组件,运行在内存管理层;PHP 是用户空间的应用程序,连 mmap 都不能直接触碰物理页帧,更无权调度 zswap 缓存或控制压缩后页面的生命周期。
为什么 PHP 进程完全感知不到 zswap
zswap 在内核中拦截写入 swap 的页面,用 LZO/LZ4 压缩后暂存于 RAM 中的专用 pool(zswap pool),它对上层进程完全透明。PHP 调用 malloc、创建数组、加载大文件 —— 这些行为触发的是用户空间堆分配或文件缓存,只有当系统真正开始 swap(比如 MemAvailable 极低)时,内核才可能把部分匿名页送进 zswap。PHP 不会收到通知,也无法通过任何扩展或函数查询“当前我的某块内存是否被 zswap 压缩了”。
常见错误现象:
• 在 php.ini 里瞎加 zswap.enabled=1(该配置项根本不存在)
• 试图用 pcntl_fork() 后调用 sysctl 修改 vm.zswap.enabled(普通用户权限不足,且修改的是全局内核参数,与 PHP 进程无关)
• 误以为启用 opcache.memory_consumption 就能“对接” zswap(Opcache 分配的是用户态共享内存,和 zswap 的压缩 page cache 完全不同)
真正影响 PHP 内存表现的内核参数有哪些
虽然 PHP 不能调用 zswap,但它的内存行为会间接受益于 zswap 是否开启 —— 前提是系统整体内存压力大。这时你该关注的是让内核更合理地使用 zswap,而不是让 PHP “接入”它:
立即学习“PHP免费学习笔记(深入)”;
-
vm.zswap.enabled=1(需 root,在/etc/sysctl.conf或/proc/sys/vm/zswap_enabled设置) -
vm.zswap.compressor=lz4(比默认 lzo 更快,适合 CPU 富余场景) -
vm.zswap.max_pool_percent=20(限制 zswap 最多吃掉 20% 物理内存,防其自身吃爆 RAM) -
vm.swappiness=10(降低主动 swap 倾向,但保留 zswap 在紧急时介入的能力)
注意:这些修改生效后,PHP 的 memory_get_usage() 和 memory_get_peak_usage() 返回值不会变化 —— 它们只统计 PHP 自己 emalloc 分配的字节数,和内核是否压缩了背后的物理页毫无关系。
PHP 开发者该做什么:别碰 zswap,盯紧三件事
你唯一可控的,是让 PHP 少制造内存压力,从而减少内核被迫启用 zswap 的概率:
- 避免一次性
file_get_contents('/huge.log')—— 改用fopen+fgets流式处理 - 清理大数组后显式调用
unset($big_array),并确认没其他变量引用它(循环引用需gc_collect_cycles()) - OPcache 启用且配置合理:
opcache.enable=1、opcache.memory_consumption=256(单位 MB)、opcache.interned_strings_buffer=16 - 检查是否有扩展泄漏:用
memory_get_usage(true)对比真实分配量,若持续增长不回落,可能是curl、pdo_mysql等扩展未正确释放资源
性能影响很实际:zswap 开启后,htop 里看到 SWAP 列几乎为 0,但 MEM 使用率略高(因为 zswap pool 占内存),PHP 请求延迟反而可能更低 —— 因为避免了慢速磁盘 swap I/O。但这不是 PHP 加速,是内核替你省了一次硬盘寻道。
最易被忽略的一点:zswap 只压缩匿名页(如 PHP 的堆内存),不压缩文件页(如 opcode cache 映射的 .php 文件)。所以哪怕你开了 zswap,OPcache 大小依然得自己管好,它不会因此自动扩容或压缩。



















