调用CreateFileMapping指定1K大小占64K虚拟内存,如何降低内存占用?
问题根源
你遇到的现象是Windows内存管理的两个默认规则导致的:
- 内存页粒度:32位Windows默认内存页大小为4KB,所有文件映射的实际提交大小都会向上取整到页大小,所以你传入1KB的参数最终映射大小为4KB是正常表现。
- 虚拟地址分配粒度:Windows默认的虚拟地址空间分配粒度为64KB,默认情况下每次调用
MapViewOfFile映射视图时,系统分配的基地址都会按64KB对齐,因此每个独立映射之间会产生64KB的地址空间间隙,3万次映射就会占用30000×64KB≈2GB的虚拟地址空间,直接耗尽32位程序默认的2GB用户态地址空间。
优化方案
- 【最优解】合并小文件映射为单个大映射:将所有小的独立映射合并为一个总大小匹配需求的大
CreateFileMapping对象,自行在映射视图内部管理不同1KB块的偏移索引。该方案下仅会占用1份64KB对齐的地址空间,总虚拟地址占用仅为总映射大小向上取整到64KB的数值,远低于2GB。 - 手动管理虚拟地址空间:如果业务逻辑必须使用独立的小映射,可先调用
VirtualAlloc预留一块足够大的连续虚拟地址空间(建议预留150MB以上即可覆盖3万×4KB的需求),后续调用MapViewOfFileEx时主动指定预留空间内的地址作为映射基址,即可跳过系统默认的64KB对齐分配规则,仅按4KB页对齐放置映射,消除64KB间隙,总虚拟地址占用可控制在120MB左右。 - 开启大地址感知扩展空间:在程序链接时添加
/LARGEADDRESSAWARE链接标志,32位程序运行在64位Windows系统下时可获得最多4GB的用户态虚拟地址空间,运行在开启了/3GB启动参数的32位Windows系统下时可获得最多3GB的用户态地址空间,可临时缓解地址不足的问题,建议配合上述两个治本方案使用。 - 复用映射对象:避免频繁创建销毁小的文件映射对象,对可复用的映射做缓存,减少总映射次数。
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

