experiment : 在私有堆和默认进程堆中, 测试能分配的堆空间总和, 每次能分配的最大堆空间

实验环境: Win7X64Sp1 + vs2008,  物理内存16GB.

实验结论:

    *  进程堆的最大Size并没有使用完剩余的物理内存
    *  每次能分配的最大堆空间接近2M, 不管是私有堆,还是进程堆, 和堆初始Size无关, 
    *  将堆空间用尽后, 累计堆空间总Size接近2000MB, 不管是私有堆,还是进程堆, 和堆初始Size无关,

 

[cpp] view plain copy
 
    1. /// @file       getHeapSize.cpp  
    2. /// @brief      尝试得到本进程堆的最大size  
    3.   
    4. #include "stdafx.h"  
    5. #include <Windows.h>  
    6. #include <tchar.h>  
    7.   
    8. #define MEMORY_REQUESTED_MB (1024 * 1024)       ///< 请求的堆尺寸单位(MB)  
    9. size_t  GetSystemPageSize();  
    10. bool    GetHeapSize(HANDLE hHeap, size_t & nSizeHeapOnce, size_t & nSizeHeap);  
    11. bool    GetHeapAllocTotal(HANDLE hHeap, size_t nSizeHeapOnce, size_t & nSizeHeapTotal); ///< 计算在堆上能分配的空间总和  
    12.   
    13. int _tmain(int argc, _TCHAR* argv[])  
    14. {  
    15.     bool    bRc             =   false;  
    16.     int     iIndex          =   0;  
    17.     size_t  nSizeHeap       =   0;  
    18.     size_t  nSizeHeapOnce   =   0;  
    19.     size_t  nSizeHeapTotal  =   0;  
    20.     HANDLE  hHeap           =   GetProcessHeap();  
    21.   
    22.     _tprintf(L"when hHeap = GetProcessHeap();\n");  
    23.     for(iIndex = 0; iIndex < 5; iIndex++)  
    24.     {  
    25.         bRc = GetHeapSize(hHeap, nSizeHeapOnce, nSizeHeap);  
    26.         _tprintf(   L"GetHeapSize() = %s, nSizeHeap = 0x%X, %.3f(MB)\n",   
    27.             bRc ? L"TRUE" : L"FALSE",   
    28.             nSizeHeap, 1.0f * nSizeHeap / MEMORY_REQUESTED_MB);  
    29.     }  
    30.   
    31.     /// 对私有堆的测试  
    32.     nSizeHeap = MEMORY_REQUESTED_MB * 10;  
    33.     hHeap = HeapCreate(0, GetSystemPageSize() * 4, nSizeHeap);  ///< 建立10MB的私有堆, 每次提交4Page  
    34.     if(NULL == hHeap)  
    35.         _tprintf(L"HeapCreate error code = 0x%x\n", GetLastError());  
    36.     else  
    37.     {  
    38.         _tprintf(L"HeapCreate Ok, nSizeHeap = %dMB\n", nSizeHeap / MEMORY_REQUESTED_MB);  
    39.         for(iIndex = 0; iIndex < 5; iIndex++)  
    40.         {  
    41.             bRc = GetHeapSize(hHeap, nSizeHeapOnce, nSizeHeap);  
    42.             _tprintf(   L"GetHeapSize() = %s, nSizeHeap = 0x%X, %.3f(MB)\n",   
    43.                 bRc ? L"TRUE" : L"FALSE",   
    44.                 nSizeHeap, 1.0f * nSizeHeap / MEMORY_REQUESTED_MB);  
    45.         }  
    46.   
    47.         HeapDestroy(hHeap);  
    48.     }  
    49.   
    50.     /// 测试从私有堆上能分配的最大空间, 依次分配一块, 计算能分配的空间总和  
    51.     nSizeHeap = MEMORY_REQUESTED_MB * 10;  
    52.     if(0 == nSizeHeapOnce)  
    53.         nSizeHeapOnce = GetSystemPageSize();  
    54.     _tprintf(L"nSizeHeapOnce = 0x%x\n", nSizeHeapOnce);  
    55.   
    56.     hHeap = HeapCreate(0, nSizeHeapOnce, nSizeHeap);    ///< 建立10MB的私有堆, 每次提交4Page  
    57.     if(NULL == hHeap)  
    58.         _tprintf(L"HeapCreate error code = 0x%x\n", GetLastError());  
    59.     else  
    60.     {  
    61.         _tprintf(L"HeapCreate Ok, nSizeHeap = %dMB\n", nSizeHeap / MEMORY_REQUESTED_MB);  
    62.         bRc = GetHeapAllocTotal(hHeap, nSizeHeapOnce, nSizeHeapTotal);  
    63.         _tprintf(   L"GetHeapAllocTotal() = %s, nSizeHeapOnce = 0x%X, %.3f(MB), nSizeHeapTotal = 0x%X, %.3f(MB)\n",   
    64.             bRc ? L"TRUE" : L"FALSE",   
    65.             nSizeHeapOnce, 1.0f * nSizeHeapOnce / MEMORY_REQUESTED_MB,  
    66.             nSizeHeapTotal, 1.0f * nSizeHeapTotal / MEMORY_REQUESTED_MB);  
    67.   
    68.         HeapDestroy(hHeap);  
    69.     }  
    70.       
    71.   
    72.     /** operating results 
    73.     将程序编译成Release + win32, 在IDE外直接运行 
    74.  
    75.     when hHeap = GetProcessHeap(); 
    76.     GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB) 
    77.     GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB) 
    78.     GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB) 
    79.     GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB) 
    80.     GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB) 
    81.     HeapCreate Ok, nSizeHeap = 10MB 
    82.     GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB) 
    83.     GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB) 
    84.     GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB) 
    85.     GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB) 
    86.     GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB) 
    87.     nSizeHeapOnce = 0x1ff000 
    88.     HeapCreate Ok, nSizeHeap = 10MB 
    89.     GetHeapAllocTotal() = TRUE, nSizeHeapOnce = 0x1FF000, 1.996(MB), nSizeHeapTotal 
    90.     = 0x7C41C000, 1988.109(MB) 
    91.  
    92.     剩余物理内存是8655M, 看来进程堆的最大Size并没有使用完剩余的物理内存 
    93.     经过多次实验, 进程堆的Size大约是1800上下几MB 
    94.  
    95.     建立10MB的私有堆, 测试出的私有堆大小为2MB左右?? 
    96.     建立了20MB的私有堆, 测试出的私有堆大小也为2MB左右. 
    97.     建立了100MB的私有堆, 测试出的私有堆大小也为2MB左右. 
    98.  
    99.     结论: 进程私有堆是程序编译时指定的, 指定多大都没用 
    100.  
    101.     在vs2008中设置对大小为10MB, 10485760 
    102.     设置步骤: vs2008工程属性 >> Configuration Properties >> Linker >> System >> Heap Reserver Size 
    103.     实验结果:  
    104.         * 每次能分配的堆空间一直2M左右, 不管是私有堆,还是进程堆, 和堆初始Size无关,  
    105.         * 能分配的堆空间总和接近2000MB, 不管是私有堆,还是进程堆, 和堆初始Size无关, 
    106.     */  
    107.   
    108.     getchar();  
    109.     return 0;  
    110. }  
    111.   
    112. bool    GetHeapAllocTotal(HANDLE hHeap, size_t nSizeHeapOnce, size_t & nSizeHeapTotal)  
    113. {  
    114.     bool        bRc             =   false;  
    115.     BYTE *      pBufHeap        =   NULL;  
    116.   
    117.     nSizeHeapTotal = 0;  
    118.     do   
    119.     {  
    120.         pBufHeap = static_cast<BYTE *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSizeHeapOnce));  
    121.         if(NULL != pBufHeap)  
    122.         {  
    123.             bRc = true;  
    124.             nSizeHeapTotal += nSizeHeapOnce;  
    125.         }  
    126.   
    127.     } while (NULL != pBufHeap);  
    128.   
    129.     return bRc;  
    130. }  
    131.   
    132. bool    GetHeapSize(HANDLE hHeap, size_t & nSizeHeapOnce, size_t & nSizeHeap)  
    133. {  
    134.     bool        bRc             =   false;  
    135.     size_t      nSystemPageSize =   GetSystemPageSize();  
    136.     int         iMultiple       =   0;          ///< 内存申请容量是SYSTEM_INFO.PageSize的倍数  
    137.     BYTE *      pBufHeap        =   NULL;  
    138.   
    139.     iMultiple = static_cast<size_t>(MEMORY_REQUESTED_MB) / nSystemPageSize;  
    140.     nSizeHeap = iMultiple * nSystemPageSize;    ///< 从1MB开始尝试  
    141.     do   
    142.     {  
    143.         pBufHeap = static_cast<BYTE *>(HeapAlloc(hHeap, HEAP_ZERO_MEMORY, nSizeHeap));  
    144.         if(NULL != pBufHeap)  
    145.         {  
    146.             if(FALSE == HeapFree(GetProcessHeap(), 0, pBufHeap))  
    147.                 return false;  
    148.         }  
    149.   
    150.         iMultiple *= 2; ///< 快速靠近堆上限制  
    151.         nSizeHeap = iMultiple * nSystemPageSize;  
    152.     } while (NULL != pBufHeap); ///< 一直尝试到失败为止  
    153.   
    154.     /// 从失败的最大Size往小申请, 第一次成功的Size就是进程堆的Size  
    155.     nSizeHeap = --iMultiple * nSystemPageSize;  
    156.     do   
    157.     {  
    158.         pBufHeap = static_cast<BYTE *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSizeHeap));  
    159.         if(NULL != pBufHeap)  
    160.         {  
    161.             if(FALSE == HeapFree(GetProcessHeap(), 0, pBufHeap))  
    162.             {  
    163.                 return false;  
    164.             }  
    165.   
    166.             bRc = true;  
    167.             nSizeHeapOnce = nSizeHeap;   
    168.             break;  
    169.         }  
    170.   
    171.         nSizeHeap = --iMultiple * nSystemPageSize;  
    172.     } while (NULL == pBufHeap); ///< 一直尝试到成功为止  
    173.   
    174.     return bRc;  
    175. }  
    176.   
    177. size_t  GetSystemPageSize()  
    178. {  
    179.     /// SYSTEM_INFO.dwPageSize : 页面大小和页保护和承诺的粒度, 是VirtualAlloc的入参  
    180.   
    181.     SYSTEM_INFO sSysInfo;  
    182.   
    183.     GetSystemInfo(&sSysInfo);  
    184.     return sSysInfo.dwPageSize;  
    185. }  

http://blog.csdn.net/lostspeed/article/details/8423215

posted @ 2018-01-19 17:13  findumars  Views(233)  Comments(0Edit  收藏  举报