【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
12、【MOD开发】【骑砍2】运行内存:游戏里的 pagefile 与虚拟内存
背景
上篇 【MOD开发】【骑砍2】运行内存:bat 与 PowerShell 语法逐行拆解 拆开了三个脚本的语法:bat 负责管理员检查和调用 PowerShell,PowerShell 通过 CIM(Common Information Model,通用信息模型)读取 Win32_ComputerSystem、Win32_PageFileSetting、Win32_PageFileUsage,再通过 PagingFiles 的 REG_MULTI_SZ 写入页面文件配置;wmic pagefileset create 的双反斜杠会让后续 where 匹配失败,所以改用注册表或图形界面。
配置层讲完之后,还需要回答一个更根本的问题:为什么增加页面文件能避免 OOM(Out of Memory,内存耗尽),为什么它又不能让游戏变快。本篇回到游戏本身,讲清虚拟地址、页表、页错误、切页和工作集在进入战场时如何共同作用。
骑砍2
🎮 游戏内存峰值从哪里来
战役地图和任务场景是两套不同的负载。地图上主要是地形、城镇、部队标记和 UI(User Interface,用户界面);进入 land_raid 之后,游戏要加载战场地形、植被、建筑、纹理、网格、动画、Agent(游戏中的行动单位)、阵型、音效和任务 UI,MOD(Modification,模组)还会在此基础上增加自己的缓存、列表和临时对象。
本次现场的游戏版本是 v1.5.6.125053,加载了 40 多个模块。进入战场约 6 秒后,游戏进程的提交量已经接近系统上限:16GB 物理内存加约 13GB 页面文件,提交限制约 30GB;游戏本身约 11GB,Steam 与 steamwebhelper 约 4.5GB,其余进程和系统占掉剩余部分。页面文件只剩 270MB 时,再申请 2.3MB 也会失败。
峰值不是均匀增长的。场景切换、纹理上传、Agent 生成和 MOD 初始化往往集中在几秒内完成,短时间内大量提交会把余量迅速吃掉。启动时看到的 3.7GB 只是早期采样,不能代表战场加载完成后的占用。
🧠 虚拟地址到 pagefile

图 1 页错误与切页路径
游戏访问的是虚拟地址,不是物理地址。CPU 发出虚拟地址后,MMU(Memory Management Unit,内存管理单元)查页表,把虚拟页翻译成物理页。页在 RAM(Random Access Memory,随机存取存储器)中时直接访问;页不在 RAM 时触发页错误,操作系统从页面文件或映射文件把页读回 RAM,更新页表,再重新执行刚才的指令。
这条路径说明了两件事。第一,页错误本身不是崩溃,它是虚拟内存的正常工作方式;只有页错误密集到影响帧时间,才会表现为卡顿。第二,页面文件不是"额外内存条",它只是换出页的后备存储;页被换出后仍然属于进程,只是暂时不在 RAM。
Windows 还会根据内存压力裁剪进程的工作集,把一段时间没有访问的页换出。工作集变小不等于进程释放了内存,提交量仍然记在进程账上;这也是"任务管理器内存不高,但提交量很大"的原因。
页面文件耗尽时,游戏可能在 native 路径里以 0xC0000005 结束;这个异常码只是失败后的表现,不能用来判断是哪个 MOD。任务管理器里的"内存"下降,也可能只是工作集被裁剪,提交量并没有下降。
🧩 Reserve、Commit 与 Working Set
| 指标 | 含义 | 观察方式 |
|---|---|---|
| Reserved | 只占虚拟地址空间,不占提交 | 进程地址空间统计 |
| Committed | 已提交,系统承诺 RAM 或页面文件 | PagedMemorySize64、提交量 |
| Working Set | 当前驻留 RAM 的页 | 任务管理器"内存"列 |
| Private Bytes | 进程私有提交量 | 性能计数器 |
保留量可以很大,提交量才是系统需要兜底的部分。工作集只反映当前在 RAM 的页,不能代表进程一共提交了多少;被换出的页仍然属于进程。
📊 pagefile 能解决/不能解决
| 维度 | 结果 | 用途 |
|---|---|---|
| 提交限制 | 页面文件增大,提交上限提高 | 避免"拿不到新内存"的分配失败 |
| 物理内存 | 不增加 | 不能替代内存条 |
| 冷页换出 | 可以把不活跃页放到磁盘 | 给当前热页腾出 RAM |
| 热页访问 | 仍需驻留 RAM | 工作集超过 RAM 时会产生密集切页 |
| 帧时间 | 切页会带来磁盘 I/O 和延迟 | 页面文件不是帧率加速器 |
| 稳定性 | 避免提交耗尽导致的 OOM | 用磁盘空间换稳定 |
把这张表压缩成一句话:页面文件解决"提交不够",不解决"物理内存不够"。提交量接近上限时,增加页面文件可以让游戏继续申请内存,避免在分配点直接失败;如果游戏真的要把大量冷页重新读回 RAM,磁盘 I/O 和页错误会变成新的瓶颈。
本次把 C 盘页面文件设为 8GB、D 盘设为 32GB,提交限制从约 30GB 提高到约 55GB。这个改动的作用是给战场加载留出余量,让 11GB 的游戏提交不再和 Steam、后台程序挤在 30GB 的上限里;它不会让 16GB 物理内存变成 48GB,也不会让纹理加载变快。
⚙️ 游戏内表现
页面文件放在 NVMe(Non-Volatile Memory Express,非易失性内存主机控制器接口规范)SSD(Solid State Drive,固态硬盘)上,切页延迟明显低于机械硬盘;但同一块 NVMe 上的页面文件和游戏资源会共享磁盘带宽,页面文件放在 D 盘不会获得额外的物理通道。页面文件放在机械硬盘上,密集切页会直接表现为长时间卡顿和加载变慢。
BattleSize(战斗规模)、植被密度、纹理质量、MOD 数量都会改变峰值。战斗规模越大,Agent 和阵型相关对象越多;植被和纹理越精细,场景加载的提交量越高;MOD 越多,初始化阶段的对象和缓存越多。页面文件只是兜底,降低峰值仍然要靠这些设置。
后台程序同样会影响结果。浏览器、编辑器、虚拟机、聊天工具都会占用提交量;Steam 的浏览器组件在多标签或长时间运行后也可能占用数 GB。进入战场前关闭不必要的后台程序,往往比继续扩大页面文件更直接。
⚙️ 页面文件放哪里、放多大
| 维度 | 结果 | 用途 |
|---|---|---|
| 系统盘 C: | 内核转储方便 | 系统盘空间紧张 |
| 数据盘 D: | 空间充足 | 与游戏资源共享同一块盘 |
| 机械硬盘 | 容量大 | 切页延迟高,容易卡顿 |
| U 盘/网络盘 | 不推荐 | Windows 不支持或性能极差 |
同一块 NVMe 上分 C/D 两个分区,页面文件放在 D 盘只改变空间归属,不增加物理通道。页面文件大小按峰值提交和磁盘余量定,不按固定倍数。
SSD 的写入寿命通常足够,但长期高频率切页说明工作集长期超过 RAM;这种情况下加内存比继续扩页面文件更有效。
✅ 验收
进入战场后观察 Commit Limit 与 Committed Bytes 的差值,保持 4GB 以上余量;同时确认 Event 2004 不再出现。若余量仍然不足,先降低 BattleSize 和后台程序,再评估是否继续扩大页面文件。
📌 一句话记忆
页面文件扩大的是提交上限,不是物理内存;它用磁盘空间换稳定性,用切页延迟换不 OOM。
📌 小结
- 游戏访问虚拟地址,页表负责翻译,页错误负责把页从页面文件搬回 RAM。
- 页面文件增加的是提交上限,不是物理内存,也不是帧率。
- 冷页换出可以腾出 RAM,热页密集切页会带来卡顿和加载变慢。
- 战场加载是峰值场景,纹理、植被、Agent、阵型和 MOD 会在短时间内集中提交。
- 页面文件放 NVMe 比机械硬盘好,但同一块盘仍然共享带宽。
- 先降低峰值和后台占用,再用页面文件兜底;页面文件不是性能加速器。
下一篇把视角从骑砍2扩展到其他应用:浏览器、IDE(Integrated Development Environment,集成开发环境)、虚拟机、剪辑软件和模拟器都可能遇到同类的提交压力,也会面对磁盘空间、SSD 写入和延迟这些限制。
OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog