看来在 Vista/Windows Server 2008 中大量使用关键部分会导致操作系统无法完全重新获得内存。
我们在 Delphi 应用程序中发现了这个问题,这显然是因为使用了 CS API。 (看这个所以问题 https://stackoverflow.com/questions/780073/is-the-memory-not-reclaimed-for-delphi-apps-running-on-windows-server-2008-sp1)
有没有其他人在使用其他语言(C++,...)开发的应用程序中看到过它?
示例代码只是初始化 10000000 CS,然后删除它们。这在 XP/Win2003 中工作正常,但在 Vista/Win2008 中不会释放所有峰值内存,直到应用程序结束。
您使用 CS 的次数越多,您的应用程序无用地保留的内存就越多。
微软确实改变了方式InitializeCriticalSection
适用于 Vista、Windows Server 2008,也可能适用于 Windows 7。
他们添加了一个“功能”,当您分配一堆 CS 时,可以保留一些用于调试信息的内存。分配的内存越多,保留的内存就越多。它可能是渐近的,并最终趋于平缓(没有完全相信这一点)。
为了避免这个“功能”,你必须使用新的 API初始化CriticalSectionEx http://msdn.microsoft.com/en-us/library/ms683477(VS.85).aspx并传递旗帜CRITICAL_SECTION_NO_DEBUG_INFO
.
这样做的优点是它可能会更快,因为通常只使用旋转计数而无需实际等待。
缺点是您的旧应用程序可能不兼容,您需要更改代码,它现在依赖于平台(您必须检查版本以确定使用哪一个)。如果需要的话,您也将失去调试的能力。
冻结 Windows Server 2008 的测试套件:
- 将此 C++ 示例构建为 CSTest.exe
#include "stdafx.h"
#include "windows.h"
#include <iostream>
using namespace std;
void TestCriticalSections()
{
const unsigned int CS_MAX = 5000000;
CRITICAL_SECTION* csArray = new CRITICAL_SECTION[CS_MAX];
for (unsigned int i = 0; i < CS_MAX; ++i)
InitializeCriticalSection(&csArray[i]);
for (unsigned int i = 0; i < CS_MAX; ++i)
EnterCriticalSection(&csArray[i]);
for (unsigned int i = 0; i < CS_MAX; ++i)
LeaveCriticalSection(&csArray[i]);
for (unsigned int i = 0; i < CS_MAX; ++i)
DeleteCriticalSection(&csArray[i]);
delete [] csArray;
}
int _tmain(int argc, _TCHAR* argv[])
{
TestCriticalSections();
cout << "just hanging around...";
cin.get();
return 0;
}
-...运行此批处理文件(需要服务器 SDK 中的 sleep.exe)
@rem you may adapt the sleep delay depending on speed and # of CPUs
@rem sleep 2 on a duo-core 4GB. sleep 1 on a 4CPU 8GB.
@for /L %%i in (1,1,300) do @echo %%i & @start /min CSTest.exe & @sleep 1
@echo still alive?
@pause
@taskkill /im cstest.* /f
-...并看到具有 8GB 和四核 CPU 的 Win2008 服务器在达到启动的 300 个实例之前冻结。
-...在 Windows 2003 服务器上重复,您会发现它处理得非常顺利。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)