单个VirtualAlloc (xxxx, yyy, MEM_RESERVE, zzz)使用了多少内存或其他资源?
当我分配一个大块时,资源消耗(例如内核分页/非分页池)是否有任何不同,如:
VirtualAlloc( xxxx, 1024*1024, MEM_RESERVE, PAGE_READWRITE )或多个较小的块,如下所示:
VirtualAlloc( xxxx, 64*1024, MEM_RESERVE, PAGE_READWRITE );
VirtualAlloc( xxxx+1*64*1024, 64*1024, MEM_RESERVE, PAGE_READWRITE );
VirtualAlloc( xxxx+2*64*1024, 64*1024, MEM_RESERVE, PAGE_READWRITE );
...
VirtualAlloc( xxxx+15*64*1024, 64*1024, MEM_RESERVE, PAGE_READWRITE );如果有人不知道答案,但可以提出一个实验,可以检查它,这也是有帮助的。
我的动机是在Windows下实现将内存返回到http://code.google.com/p/google-perftools/操作系统。我的想法是通过执行一系列小的(分配粒度)调用来替换单个的大型VirtualAlloc调用,这样我就可以对每个调用调用VirtualFree。我知道这样做的话,大楼宇的分配便会较慢,但会否受到资源消耗的惩罚呢?
发布于 2010-08-18 16:56:35
只是FYI,您可以使用GetProcessMemoryInfo和GlobalMemoryStatusEx来获得一些内存使用情况。
void DisplayMemoryUsageInformation()
{
HANDLE hProcess = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
ZeroMemory(&pmc,sizeof(pmc));
GetProcessMemoryInfo(hProcess,&pmc, sizeof(pmc));
std::cout << "PageFaultCount: " << pmc.PageFaultCount << std::endl;
std::cout << "PeakWorkingSetSize: " << pmc.PeakWorkingSetSize << std::endl;
std::cout << "WorkingSetSize: " << pmc.WorkingSetSize << std::endl;
std::cout << "QuotaPeakPagedPoolUsage: " << pmc.QuotaPeakPagedPoolUsage << std::endl;
std::cout << "QuotaPagedPoolUsage: " << pmc.QuotaPagedPoolUsage << std::endl;
std::cout << "QuotaPeakNonPagedPoolUsage: " << pmc.QuotaPeakNonPagedPoolUsage << std::endl;
std::cout << "QuotaNonPagedPoolUsage: " << pmc.QuotaNonPagedPoolUsage << std::endl;
std::cout << "PagefileUsage: " << pmc.PagefileUsage << std::endl;
std::cout << "PeakPagefileUsage: " << pmc.PeakPagefileUsage << std::endl;
MEMORYSTATUSEX msx;
ZeroMemory(&msx,sizeof(msx));
msx.dwLength = sizeof(msx);
GlobalMemoryStatusEx(&msx);
std::cout << "MemoryLoad: " << msx.dwMemoryLoad << std::endl;
std::cout << "TotalPhys: " << msx.ullTotalPhys << std::endl;
std::cout << "AvailPhys: " << msx.ullAvailPhys << std::endl;
std::cout << "TotalPageFile: " << msx.ullTotalPageFile << std::endl;
std::cout << "AvailPageFile: " << msx.ullAvailPageFile << std::endl;
std::cout << "TotalVirtual: " << msx.ullTotalVirtual << std::endl;
std::cout << "AvailVirtual: " << msx.ullAvailVirtual << std::endl;
std::cout << "AvailExtendedVirtual: " << msx.ullAvailExtendedVirtual << std::endl;
}发布于 2010-08-19 01:46:49
零(或实际上为零)内存是通过使用保留参数进行VirtualAlloc调用来使用的。这将只保留进程中的地址空间。在实际使用VirtualAlloc和commit参数使用页面备份地址之前,不会使用内存。这实质上是虚拟字节、占用的地址空间和私有字节、提交的内存量之间的区别。VirtualAlloc()的两种使用都将保留相同数量的内存,因此它们在资源消耗方面是等价的。我建议您在决定编写自己的分配器之前对此进行一些阅读。最好的消息来源之一是马克·鲁斯尼维奇。你应该检查一下他的博客。他写了几篇文章,叫做“突破极限”,涵盖了其中的一些内容。如果你想了解真正的细节,那么你应该读他的书(Microsoft Windows内部组件)。到目前为止,这是我所读到的关于windows如何管理内存(以及其他一切)的最好参考。
(编辑)补充资料:有关的部分是“网页目录”和“页表”。根据我以前的微软视窗内部版本..。在x86上,每个进程都有一个包含1024个条目的单一页面目录。有多达512页的表格。进程中使用的每个32位指针被分成3部分:31-22页目录索引,21-12是页面表索引,11-0是页面中的字节索引。当您在预留参数中使用虚拟分配时,将创建条目(32位),并创建Page条目32位。此时,页不是为保留内存创建的。查看此信息的最佳方法是使用内核调试器。我建议使用LiveKD (sysinternals)。您可以在不附加远程计算机的情况下使用liveKD,但它不允许实时调试。加载LiveKD,并选择您的进程。然后可以运行!PTE命令来检查进程的页表。
再一次,我建议阅读Windows内部的内容。在我的版本(第4版)中,有一章(超过100页)用示例介绍了所有这一切,以便在liveKD中遍历各种数据结构。
发布于 2010-08-09 11:37:01
根据我对页面表的理解,您有块,例如1024页,每页有一个单词。在任何情况下,代价都是页数,而不是分配。事实上,可能还有其他机制需要“额外”的分配(我只是不知道)。
尽管如此:使用VirtualFree,您可以有选择地将分解为各个页面或页面范围。对于已解压缩的页面,虚拟地址范围(在您的进程中)仍然是保留的,但是没有为其分配物理内存(RAM或交换文件)。稍后您可以使用VirtualAlloc再次提交这些页面。
因此,除非您需要为进程中的其他分配程序释放地址空间,否则可以使用此机制选择性地请求内存并将内存返回到操作系统。
编辑
测量
为了测量,我想比较两种算法在一个或多个典型负载下的性能(人工/随机分配模式、分配量大的“真实世界”应用程序等)。优点:你得到了“整个故事”-内核资源,页面分割,应用程序性能等等。缺点:你必须实现这两种算法,你不知道原因,你可能需要非常特殊的情况下,一个可测量的差异,突出的噪音。
地址空间碎片警告-小心您的返回算法。当以“谁是自由的人”的方式返回单个页面到进程时,您可能会得到一个碎片地址空间,它有80%的空闲内存,但没有连续100 K的内存。
https://stackoverflow.com/questions/3439435
复制相似问题