You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VMMap与任务管理器内存显示差异及技术疑问

Windows内存实验:Committed Size vs Working Set 差异验证

为验证Committed Size可能小于Working Set,我开展了如下实验:

实验步骤

1. 编译大体积DLL并复制为多份

编写包含大常量数据段的DLL项目,编译后重命名为5个不同的DLL文件,代码如下:

// LargeDLL.cpp
#include <windows.h>

const BYTE g_largeData[50 * 1024 * 1024] = { 0 };

extern "C" __declspec(dllexport) void DummyFunction() {
    volatile int dummy = g_largeData[0];
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    return TRUE;
}

2. 编写加载多DLL的测试程序

编写程序循环加载上述5个DLL,并调用导出函数触发数据段访问,代码如下:

// TestDLLLoad.cpp
#include <windows.h>
#include <iostream>
#include <vector>

typedef void (*DummyFunc)();

int main() {
    std::vector<HMODULE> loadedDLLs;

    const char* dllNames[] = {
        "LargeDLL_A.dll",
        "LargeDLL_B.dll",
        "LargeDLL_C.dll",
        "LargeDLL_D.dll",
        "LargeDLL_E.dll"
    };

    for (const char* dllName : dllNames) {
        HMODULE hDLL = LoadLibraryA(dllName);
        if (hDLL == NULL) {
            std::cerr << "Failed to load " << dllName << ", error: " << GetLastError() << std::endl;
            return 1;
        }
        loadedDLLs.push_back(hDLL);

        DummyFunc func = (DummyFunc)GetProcAddress(hDLL, "DummyFunction");
        if (func) {
            func();
        }
    }

    std::cout << "All DLLs loaded. Check Task Manager now. Press Enter to exit..." << std::endl;
    std::cin.get();

    for (auto hDLL : loadedDLLs) {
        FreeLibrary(hDLL);
    }

    return 0;
}

实验结果

VMMap 内存统计

[Type]        [Committed]  [Private]  [Total Working Set]  [Private Working Set]  [Shareable Working Set]
Total         321,124K     1,612K     5,380K              1,180K                4,200K
Heap          196K         132K       136K                132K                  4K
Image         318,584K     636K       4,088K              228K                  3,860K
MappedFile    1,260K       0K         124K                0K                    124K
PageTable     780K         780K       780K                780K                  0K
PrivateData   32K          32K        28K                 20K                   8K
Sharable      240K         0K         204K                0K                    204K
Stack         32K          32K        20K                 20K                   0K

任务管理器内存统计

Working Set (memory): 4,632K
Private Working Set (memory): 432K
Sharable Working Set (memory): 4,200K
Commit Size: 1,644K

技术疑问与解答

疑问1:VMMap与任务管理器的Private Working Set、总Working Set数值差异原因

VMMap的Private Working Set包含进程的页表(PageTable)内存,而任务管理器的Private Working Set会排除页表。除此之外,VMMap的统计还包含内核模式下为进程分配的私有辅助结构,这些内容不会被任务管理器归类到进程私有内存中;任务管理器仅统计用户模式下的私有可写内存、私有堆、栈等。

总Working Set的差异源于VMMap的Total Working Set是所有类型内存的Working Set总和,包含部分任务管理器不统计的内核关联内存项;而任务管理器的Working Set仅计算Private Working Set与Sharable Working Set的和,因此两者数值不同。

疑问2:VMMap与任务管理器的Commit Size数值差异原因

VMMap的Committed统计的是进程地址空间中所有标记为已提交的内存范围,包括:

  • DLL整个镜像文件的大小(包括未被访问的50MB零初始化数据段,Windows会标记为已提交但延迟加载);
  • 页表、映射文件的已提交部分等。

而任务管理器的Commit Size仅统计进程实际消耗的、无法与其他进程共享的提交内存:

  • DLL的只读/可执行段是共享的,不计入进程Commit Size;
  • 零初始化数据段未被访问时,Windows不会分配物理页,也不计入Commit Size;仅被访问的部分(每个DLL仅触发1个4KB页)会被统计;
  • 仅包含进程私有堆、栈、私有数据页等非共享提交内存。

你的5个DLL仅触发了5个4KB私有数据页提交,加上进程自身的堆、栈等开销,总和接近1644K;而VMMap统计了所有DLL的镜像大小,因此出现321124K的大数值。


内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 13:55:58