7

가능한 중복 :

C ++에서 프로세스의 WorkingSet을 1GB로 강제 설정할 수있는 방법이 있습니까?

페이지 폴트를 피하기 위해 .NET 프로세스의 WorkingSet을 1GB로 미리 늘려야합니다.

.NET에서이 작업을 수행 할 수있는 방법이 있습니까?

최신 정보

불행히도, 우리가 전화를하더라도SetProcessWorkingSetSizeEx가비지 콜렉션은 MinWorkingSet을 우회하여 작업 세트를 어쨌든 트리밍합니다 (아래 다이어그램의 "자동 GC.Collect ()"참조).

아래 그림에서 새 메모리를 프로세스에 할당 할 때 발생하는 페이지 오류 (빨간색 선)가 발생하지 않도록 프로세스 WorkingSet (녹색 선)을 1GB로 잠글 수있는 방법이 있습니까?

이것이 끔찍한 이유는 페이지 폴트가 발생할 때마다 애플리케이션 성능을 크게 저하시키는 250us 스레드를 차단하기 때문입니다.

enter image description here

최신 정보

인용구 : "C / C ++, 제 5 판, Jeffrey Richter (Wintellect)를 통한 Windows"

개별 프로세스에 의한 SetProcessWorkingSetSize에 대한 호출은 무시됩니다.   프로세스가 작업 세트를 비우려고 시도하는 것이 아닌 한. 설정   이 제한에서 JOB_OBJECT_LIMIT_WORKINGSET 플래그를 지정하십시오.   LimitFlags 멤버.

이 책은 워킹 셋을 설정하는 유일한 방법은 프로세스를 작업 객체에 할당하고 JOB_OBJECT_LIMIT_WORKINGSET 및 MinimumWorkingSetSize를 설정하는 것이다.

최신 정보

SetProcessWorkingSetSizeEx는 소프트 페이지 폴트와 전혀 관련이 없습니다. 하드 페이지 오류는 현재 WorkingSet의 메모리가 하드 드라이브로 페이징되는 것을 방지하기 때문에 발생합니다.

최신 정보

WorkingSet을 늘리는 유일한 방법은 .NET을 매우 전문화 된 방식으로 실행하는 것입니다CLR 호스트C + +로 작성된 (내 대답을 참조하십시오).


  • 메모리를 차지할 버퍼를 만들 수 있습니다. 그런 다음 필요할 때 버퍼를 채울 수 있습니다. - LMS
  • < a href = "를 호출하여 작업 세트를 원하는대로 Windows에 알릴 수 있습니다.msdn.microsoft.com/en-us/library/windows/desktop/…"SetProcessWorkingSetSize< / a > < a href = "pinvoke.net/default.aspx/…> - Gabe
  • @Yahia : Gravitas가 SE_INC_BASE_PRIORITY_NAME을 (를) 사용하여 프로세스를 실행하고 있지 않아서 아니 었습니까? - Gabe
  • GC가 전화를 걸 수도 있습니다.SetProcessWorkingSizeEx작업 집합을 줄입니다. - Gabe
  • @OP :이 질문과 주석의 진술에주의하십시오. 많은 사람들이 신뢰받지 못합니다. Windows에서 가상 메모리가 작동하는 방식에 대한 많은 오해를 발견 할 수 있습니다. - usr

5 답변


4

원하는 것을 얻으려면 전화를 걸거나 핀볼을 사용해야합니다.SetWorkingSetSizeEx최소 1GB (두 번째 매개 변수) 및QUOTA_LIMITS_HARDWS_MIN_ENABLE네 번째 매개 변수로, 작업 크기가 시스템의 "높은 메모리 부족"조건에서도 최소한으로 떨어지지 않도록합니다.

시스템 동작은 또한 필요할 수있는 OS 버전 등에 따라 호출자의 권한에 따라 다릅니다.SE_INC_WORKING_SET_NAME및 / 또는SE_INC_BASE_PRIORITY_NAME!

"배후"에서 이러한 API를 사용하는 다른 (더 멋진) 옵션은 찾을 수있는 .NET 래퍼입니다.이리.


  • 게시 할 예정 이었지만 XP 및 이전 버전에서는 지원되지 않습니다. - Gabe
  • @Gabe 우리는 Windows Server 2008 R2를 사용하고 있으므로 XP를 지원할 필요가 없습니다. - Contango
  • @Yahia 권한을 사용하는 법을 보여주는 멋진 코드가 있습니다.processprivileges.codeplex.com. 이번 주말에 코드를 사용해 보겠습니다. - Contango
  • @Yahia 나는 당신이 옳다고 생각합니다. 의 코드는gate.upm.ro/os/Laborator/Utilitare_sistem_Windows/testlimit.cEnablePrivilege (SE_INC_BASE_PRIORITY_NAME)에 대한 호출이 있어야 함을 보여줍니다. SetWorkingSetSizeEx 호출 전에. 그것의 C에서, C #,하지만 나는 그것이 개념을 보여줄 것 같아요. - Contango

3

문제가 발생하면 프로세스가 메모리 부족 상황에서 너무 적극적으로 손질을하고 있다는 것이 었으면 문제를 해결할 수 있습니다.SetProcessWorkingSetSize또는 그냥 설정Process.CurrentProcess.MinWorkingSet.

그래도 표시된 것은 작업 세트가 GC에 의해 줄어들고 있다는 것입니다. 이것은 실제로 일어나고있는 일은 GC가 당신의 WS를 구성하는 페이지의 할당을 해제하고 있다는 것을 말해줍니다. 이 경우 작업 세트 문제가 아닌 주소 공간 문제가 발생하며이를 방지하기 위해 시스템 호출을 할 수 없습니다. 이상적으로는 메모리를 OS로 반환하지 않도록 GC에 알릴 수 있지만 .NET에는 이와 같은 기능이 없습니다.

주소 공간 문제를 해결하려면 이미 할당 한 객체를 다시 사용해야합니다. 대형 오브젝트 힙에 문제가있는 경우, 콜렉션이 원인 일 가능성이 큽니다. 예를 들어, 새 배열 / 목록 / 사전을 만드는 대신Clear메서드를 호출하고 다시 사용하십시오. 문제가 문자열 인 경우, 사용하지 않고 도망 갈 수 있습니다.StringBuilderLOH에서 벗어나야합니다.

특정 유형의 오브젝트를 많이 작성하는 경우 재활용되는 풀을 만드는 것을 고려하십시오. 그런 일은 한번도 해본 적이 없지만, 구현하려고한다면 정적 팩터 리 메소드를 사용하여 객체를 생성합니다. 정적 팩토리 메소드를 사용하면 객체를 풀에서 꺼내 public 생성자 대신 초기 화기를 호출하고 finalizer를 넣을 수 있습니다. 다시 풀에 넣고 그 안에있는 모든 참조를 널 (NULL)로 만듭니다. 필요에 따라 수영장은ConcurrentBag<WeakReference<T>>.


  • 불행히도, GC.Collect ()가 실행되면 워크 세트를 작은 것으로 리셋합니다. 50MB. 작업 세트를 1GB로 영구적으로 설정하는 방법이 있습니까? - Contango
  • @Gravitas 이것은 매우 흥미로운 질문입니다.이 문제가 해결되면 알려주십시오. - l--''''''---------''''''''''''
  • 당신이 전화를 해야하는 것을 피하기 위해 @GravitasSetWorkingSetSizeEx(자세한 내용은 내 답변 참조) ... - Yahia
  • @Yahia : Gravitas가 SE_INC_BASE_PRIORITY_NAME을 (를) 사용하여 프로세스를 실행하고 있지 않아서 아니 었습니까? - Gabe
  • @ Yahia QUOTA_LIMITS_HARDWS_MIN_ENABLE과 함께 SetProcessWorkingSizeEx를 사용하여 시도했지만 GC.Collect ()가 호출되면 작업 세트가 어쨌든 다듬어집니다. - Contango

2

나는 Job Object에 프로세스를 할당하고 설정하는 것JOB_OBJECT_LIMIT_WORKINGSETMinimumWorkingSetSize일할 수도 있습니다.


  • 우수 의견, 월요일에 시도해 보겠습니다. - Contango

2

소프트 페이지 오류를 줄이기 위해 .NET에서 프로세스의 WorkingSet을 늘리는 유일한 방법은 사용자 지정 아래에서 전체 .NET 응용 프로그램을 실행하는 것입니다CLR 호스트. 이는 약 800 줄의 맞춤 작성된 다소 밀도가 높은 C ++ 코드가 필요한 간단한 작업입니다. C ++ 코드는 .NET 호출을 가로 채어 Win32 메모리 관리 메서드를 호출하고 .NET 런타임의 동작을 변경하므로 일반적으로 메모리를 적극적으로 해제하지 않습니다.

이는 응용 프로그램이 시작될 때 소프트 페이지 폴트를 모두 발생 시키므로, 일반 응용 프로그램 실행 중에 .NET 응용 프로그램의 소프트 페이지 폴트 수가 거의 0으로 떨어집니다.

이것은 응용 프로그램이 메모리가 부족할 수도 있지만 더 빠르게 실행된다는 것을 의미합니다. 즉, 실시간 성능 향상을 위해 메모리 사용량을 희생합니다.


1

여기에 오해가 있다고 생각합니다 : 사용되지 않는 메모리를 확보하는 GC는좋은. WS 메트릭에서 더 높은 숫자를보기 위해 계속 유지하는 것은 쓸모가 없습니다.필요WS에서 사용되지 않는 메모리. 잘못된 측정 항목을 최적화하고 있습니다.

페이지 폴트의 수는 소프트 및 하드 폴트가 있기 때문에 의미가 없습니다. 하드 결함은 디스크에서 읽습니다. 소프트 결함은 대부분의 경우 아무 의미가 없습니다. 그것들은 OS의 구현 세부 사항입니다. 예를 들어, 새로 할당 된 모든 페이지에 대해 소프트 폴트가 발생합니다.

빨간색 그래프에 단단한 오류가 표시되지 않는다는 증거가 있습니다. 결국 500 / sec 정도가 나타납니다. 디스크가 500 IOP를 전달할 수 없으므로 하드 결함이 될 수 없습니다.

하드 결함 만 측정 (및 줄이기)하고 싶을 것입니다. 하드 결함 만이 의미있는 방식으로 성능에 영향을 미칩니다.

또한 WS 한계를 설정해도 GC에 영향을 미치지 않습니다. GC는 운영 체제 구성 요소가 아닙니다. Is는 사용자 모드 라이브러리입니다. 운영 체제가 작업 세트로 사용하기로 결정한 것과는 아무런 관련이 없습니다. 이러한 이유로 WS 한계를 설정하여 GC가 메모리를 해제하지 못하게 할 수 있습니다.

그렇다면 GC가 실행될 때 WS가 왜 줄어들까요? GC삭제약간의 기억. 일부 WS 제한을 설정해도 메모리 삭제를 막을 수는 없습니다.

의견에서 GC는 자체적으로 작업 집합을 줄이기 위해 일부 API를 호출 할 수도 있다고 제안했습니다. 왜 그렇게 할 수 있는지 전혀 알 수 없습니다. 왜 GC가 페이지를 강제로 제거합니까? 주의 사항 : WS와 할당 된 페이지는 동일하지 않습니다 (전혀!). GC는해제기억. WS가 축소되는 것을 강제하지 않습니다. 그 목적은 무엇입니까?


  • 나는 또한 OP가 단지 소프트 결함을 무시해야한다고 생각했으나 그는 "페이지 폴트가 발생할 때마다 스레드가 250us를 차단합니다."라고 게시 한 것을 보았습니다. & quot; GC 후 250us 지연을 없애는 방법 & quot;이라는 질문을 원하십니까? - Gabe
  • 이것은 다른 질문입니다. 이 250us 지연 측정 방법이 어떻게 소프트 결함으로 추적되었는지 알기를 바랍니다. 나는 부드러운 결함 성능이 GC 성능보다 높다는 것을 상상할 수 없다. - usr
  • @usr Visual Studio 2012에서 사용할 수있는 Microsoft Concurrency Visualizer를 사용하여 250us 지연을 측정했습니다. 소프트 페이지 오류가 발생하여 시스템의 다른 스레드가 실행되지 못하는 것으로 나타났습니다. - Contango

연결된 질문


관련된 질문

최근 질문