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

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

实验结论:

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

/// @file		getHeapSize.cpp
/// @brief		尝试得到本进程堆的最大size

#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>

#define MEMORY_REQUESTED_MB (1024 * 1024)		///< 请求的堆尺寸单位(MB)
size_t	GetSystemPageSize();
bool	GetHeapSize(HANDLE hHeap, size_t & nSizeHeapOnce, size_t & nSizeHeap);
bool	GetHeapAllocTotal(HANDLE hHeap, size_t nSizeHeapOnce, size_t & nSizeHeapTotal);	///< 计算在堆上能分配的空间总和

int _tmain(int argc, _TCHAR* argv[])
{
	bool	bRc				=	false;
	int		iIndex			=	0;
	size_t	nSizeHeap		=	0;
	size_t	nSizeHeapOnce	=	0;
	size_t	nSizeHeapTotal	=	0;
	HANDLE	hHeap			=	GetProcessHeap();

	_tprintf(L"when hHeap = GetProcessHeap();\n");
	for(iIndex = 0; iIndex < 5; iIndex++)
	{
		bRc = GetHeapSize(hHeap, nSizeHeapOnce, nSizeHeap);
		_tprintf(	L"GetHeapSize() = %s, nSizeHeap = 0x%X, %.3f(MB)\n", 
			bRc ? L"TRUE" : L"FALSE", 
			nSizeHeap, 1.0f * nSizeHeap / MEMORY_REQUESTED_MB);
	}

	/// 对私有堆的测试
	nSizeHeap = MEMORY_REQUESTED_MB * 10;
	hHeap = HeapCreate(0, GetSystemPageSize() * 4, nSizeHeap);	///< 建立10MB的私有堆, 每次提交4Page
	if(NULL == hHeap)
		_tprintf(L"HeapCreate error code = 0x%x\n", GetLastError());
	else
	{
		_tprintf(L"HeapCreate Ok, nSizeHeap = %dMB\n", nSizeHeap / MEMORY_REQUESTED_MB);
		for(iIndex = 0; iIndex < 5; iIndex++)
		{
			bRc = GetHeapSize(hHeap, nSizeHeapOnce, nSizeHeap);
			_tprintf(	L"GetHeapSize() = %s, nSizeHeap = 0x%X, %.3f(MB)\n", 
				bRc ? L"TRUE" : L"FALSE", 
				nSizeHeap, 1.0f * nSizeHeap / MEMORY_REQUESTED_MB);
		}

		HeapDestroy(hHeap);
	}

	/// 测试从私有堆上能分配的最大空间, 依次分配一块, 计算能分配的空间总和
	nSizeHeap = MEMORY_REQUESTED_MB * 10;
	if(0 == nSizeHeapOnce)
		nSizeHeapOnce = GetSystemPageSize();
	_tprintf(L"nSizeHeapOnce = 0x%x\n", nSizeHeapOnce);

	hHeap = HeapCreate(0, nSizeHeapOnce, nSizeHeap);	///< 建立10MB的私有堆, 每次提交4Page
	if(NULL == hHeap)
		_tprintf(L"HeapCreate error code = 0x%x\n", GetLastError());
	else
	{
		_tprintf(L"HeapCreate Ok, nSizeHeap = %dMB\n", nSizeHeap / MEMORY_REQUESTED_MB);
		bRc = GetHeapAllocTotal(hHeap, nSizeHeapOnce, nSizeHeapTotal);
		_tprintf(	L"GetHeapAllocTotal() = %s, nSizeHeapOnce = 0x%X, %.3f(MB), nSizeHeapTotal = 0x%X, %.3f(MB)\n", 
			bRc ? L"TRUE" : L"FALSE", 
			nSizeHeapOnce, 1.0f * nSizeHeapOnce / MEMORY_REQUESTED_MB,
			nSizeHeapTotal, 1.0f * nSizeHeapTotal / MEMORY_REQUESTED_MB);

		HeapDestroy(hHeap);
	}
	

	/** operating results
	将程序编译成Release + win32, 在IDE外直接运行

	when hHeap = GetProcessHeap();
	GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x70CBF000, 1804.746(MB)
	HeapCreate Ok, nSizeHeap = 10MB
	GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB)
	GetHeapSize() = TRUE, nSizeHeap = 0x1FF000, 1.996(MB)
	nSizeHeapOnce = 0x1ff000
	HeapCreate Ok, nSizeHeap = 10MB
	GetHeapAllocTotal() = TRUE, nSizeHeapOnce = 0x1FF000, 1.996(MB), nSizeHeapTotal
	= 0x7C41C000, 1988.109(MB)

	剩余物理内存是8655M, 看来进程堆的最大Size并没有使用完剩余的物理内存
	经过多次实验, 进程堆的Size大约是1800上下几MB

	建立10MB的私有堆, 测试出的私有堆大小为2MB左右??
	建立了20MB的私有堆, 测试出的私有堆大小也为2MB左右.
	建立了100MB的私有堆, 测试出的私有堆大小也为2MB左右.

	结论: 进程私有堆是程序编译时指定的, 指定多大都没用

	在vs2008中设置对大小为10MB, 10485760
	设置步骤: vs2008工程属性 >> Configuration Properties >> Linker >> System >> Heap Reserver Size
	实验结果: 
		* 每次能分配的堆空间一直2M左右, 不管是私有堆,还是进程堆, 和堆初始Size无关, 
		* 能分配的堆空间总和接近2000MB, 不管是私有堆,还是进程堆, 和堆初始Size无关,
	*/

	getchar();
	return 0;
}

bool	GetHeapAllocTotal(HANDLE hHeap, size_t nSizeHeapOnce, size_t & nSizeHeapTotal)
{
	bool		bRc				=	false;
	BYTE *		pBufHeap		=	NULL;

	nSizeHeapTotal = 0;
	do 
	{
		pBufHeap = static_cast<BYTE *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSizeHeapOnce));
		if(NULL != pBufHeap)
		{
			bRc = true;
			nSizeHeapTotal += nSizeHeapOnce;
		}

	} while (NULL != pBufHeap);

	return bRc;
}

bool	GetHeapSize(HANDLE hHeap, size_t & nSizeHeapOnce, size_t & nSizeHeap)
{
	bool		bRc				=	false;
	size_t		nSystemPageSize	=	GetSystemPageSize();
	int			iMultiple		=	0;			///< 内存申请容量是SYSTEM_INFO.PageSize的倍数
	BYTE *		pBufHeap		=	NULL;

	iMultiple = static_cast<size_t>(MEMORY_REQUESTED_MB) / nSystemPageSize;
	nSizeHeap = iMultiple * nSystemPageSize;	///< 从1MB开始尝试
	do 
	{
		pBufHeap = static_cast<BYTE *>(HeapAlloc(hHeap, HEAP_ZERO_MEMORY, nSizeHeap));
		if(NULL != pBufHeap)
		{
			if(FALSE == HeapFree(GetProcessHeap(), 0, pBufHeap))
				return false;
		}

		iMultiple *= 2;	///< 快速靠近堆上限制
		nSizeHeap = iMultiple * nSystemPageSize;
	} while (NULL != pBufHeap);	///< 一直尝试到失败为止

	/// 从失败的最大Size往小申请, 第一次成功的Size就是进程堆的Size
	nSizeHeap = --iMultiple * nSystemPageSize;
	do 
	{
		pBufHeap = static_cast<BYTE *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSizeHeap));
		if(NULL != pBufHeap)
		{
			if(FALSE == HeapFree(GetProcessHeap(), 0, pBufHeap))
			{
				return false;
			}

			bRc = true;
			nSizeHeapOnce = nSizeHeap; 
			break;
		}

		nSizeHeap = --iMultiple * nSystemPageSize;
	} while (NULL == pBufHeap);	///< 一直尝试到成功为止

	return bRc;
}

size_t	GetSystemPageSize()
{
	/// SYSTEM_INFO.dwPageSize : 页面大小和页保护和承诺的粒度, 是VirtualAlloc的入参

	SYSTEM_INFO	sSysInfo;

	GetSystemInfo(&sSysInfo);
	return sSysInfo.dwPageSize;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值