문제

Vista/Windows Server 2008에서 중요한 섹션을 많이 사용하면 OS가 메모리를 완전히 회복하지 못하는 것으로 보입니다. 우리는 델파이 응용 프로그램 에서이 문제를 발견했으며 CS API를 사용하기 때문입니다. (이것 좀 봐 그래서 질문)

다른 언어 (C ++, ...)로 개발 된 응용 프로그램으로 다른 사람이 본 적이 있습니까?

샘플 코드는 단지 10000000 CS를 초기화 한 다음 삭제했습니다. 이것은 XP/Win2003에서 잘 작동하지만 응용 프로그램이 종료 될 때까지 Vista/Win2008에서 모든 피크 메모리를 해제하는 것은 아닙니다.
CS를 더 많이 사용할수록 응용 프로그램은 더 많은 메모리를 보유하지 않습니다.

도움이 되었습니까?

해결책

Microsoft는 실제로 길을 바 꾸었습니다 InitializeCriticalSection Vista, Windows Server 2008 및 아마도 Windows 7에서 작동합니다.
CS를 할당 할 때 디버그 정보에 사용되는 메모리를 유지하기 위해 "기능"을 추가했습니다. 할당할수록 더 많은 기억이 유지됩니다. 점근적일 수 있고 결국 평평해질 수 있습니다 (이것에 완전히 구입하지 않음).
이 "기능"을 피하려면 새 API를 사용해야합니다. initalizecriticalSectionEx 그리고 깃발을 통과하십시오 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

-... 300 인스턴스에 도달하기 전에 8GB 및 쿼드 CPU 코어 냉동이있는 Win2008 서버를 참조하십시오.
-... Windows 2003 서버에서 반복하여 매력처럼 처리하는 것을보십시오.

다른 팁

시험은 아마도 문제를 대표하지 않을 것입니다. 중요 섹션을 초기화 할 때 실제 커널 뮤트가 생성되지 않기 때문에 임계 섹션은 "경량 뮤텍스"로 간주됩니다. 이것은 당신의 10m 중요 섹션이 단순한 회원 몇 명만있는 구조 일뿐입니다. 그러나 두 스레드가 동시에 CS에 액세스 할 때, 그것들을 동기화하기 위해 뮤텍스가 실제로 생성됩니다. 그리고 그것은 다른 이야기입니다.

테스트 앱과 달리 실제 앱 스레드가 충돌한다고 가정합니다. 이제 중요한 섹션을 가벼운 뮤 테스로 처리하고 많은 부분을 생성하는 경우 앱이 가벼운 중요한 섹션 객체보다 훨씬 무겁습니다. 그리고 뮤 테스는 커널 객체이므로 과도한 수의 수를 생성하면 실제로 OS를 해칠 수 있습니다.

이것이 사실이라면, 많은 충돌을 기대하는 중요한 섹션의 사용을 줄여야합니다. 이것은 Windows 버전과 관련이 없으므로 내 추측이 잘못되었을 수도 있지만 여전히 고려해야 할 사항입니다. OS 핸들 수 모니터링을 시도하고 앱의 수행 방식을 확인하십시오.

당신은 다른 것을보고 있습니다.

방금이 테스트 코드를 구축하고 실행했습니다. 모든 메모리 사용 통계는 일정합니다 - 개인 바이트, 작업 세트, 커밋 등이 있습니다.

int _tmain(int argc, _TCHAR* argv[])
{
    while (true)
    {
        CRITICAL_SECTION* cs = new CRITICAL_SECTION[1000000];
        for (int i = 0; i < 1000000; i++) InitializeCriticalSection(&cs[i]);
        for (int i = 0; i < 1000000; i++) DeleteCriticalSection(&cs[i]);
        delete [] cs;
    }

    return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top