개인 바이트, 가상 바이트, 작업 세트 란 무엇입니까?


490

프로세스에서 메모리 누수를 디버깅하기 위해 perfmon windows 유틸리티를 사용하려고합니다.

이것이 perfmon이 다음과 같은 용어를 설명하는 방법입니다.

작업 집합 은이 프로세스의 작업 집합의 현재 크기 (바이트)입니다. 작업 세트는 프로세스의 스레드가 최근에 터치 한 메모리 페이지 세트입니다. 컴퓨터의 사용 가능한 메모리가 임계 값을 초과하면 사용하지 않더라도 프로세스의 작업 세트에 페이지가 남습니다. 사용 가능한 메모리가 임계 값 아래로 떨어지면 작업 세트에서 페이지가 잘립니다. 필요한 경우 메인 메모리를 떠나기 전에 작업 세트로 소프트 오류가 발생합니다.

가상 바이트 는 프로세스가 사용중인 가상 주소 공간의 현재 크기 (바이트)입니다. 가상 주소 공간을 사용한다고해서 반드시 디스크 나 기본 메모리 페이지를 사용하는 것은 아닙니다. 가상 공간은 유한하며 프로세스는 라이브러리를로드하는 기능을 제한 할 수 있습니다.

개인 바이트 는이 프로세스가 할당 한 다른 프로세스와 공유 할 수없는 메모리의 현재 크기 (바이트)입니다.

이것들은 내가 가진 질문입니다.

프로세스가 공유 라이브러리를 포함하지 않고 누출이 발생하면 프로세스 자체에서 발생하기 때문에 프로세스에 누출이 있는지 확인하기 위해 측정 해야하는 개인 바이트입니까?

프로세스가 소비 한 총 메모리는 얼마입니까? 가상 바이트입니까 아니면 가상 바이트와 작업 세트의 합입니까?

프라이빗 바이트, 워킹 세트 및 가상 바이트 사이에 관계가 있습니까?

메모리 사용에 대한 더 나은 아이디어를 제공하는 다른 도구가 있습니까?


3
더 나은 도구는 Valgrind의 / helgrind 있지만 :( 불행히도 Windows에서 것
코넬 Kisielewicz

그것은 개인 바이트 내가 프로세스가 어떤 누출을 가지고 있는지 확인하는 경우로 측정해야인가요 경우 개인 바이트 프로세스의 다음 성장하지 않는 더 메모리 누수가 없다. 증가하면 메모리 누수로 인한 것일 수 있으며 메모리 조각화 때문일 수 있습니다. 개인 바이트의 성장을 정확히 말하는 것이 어렵다고 생각합니다 .

@SergeiKurenkov 우리가 말할 수있는 한 가지는 "메모리 조각화"때문이 아니라는 것입니다.
Jamie Hanrahan

답변:


517

이 질문에 대한 짧은 대답 은 이러한 값 중 어느 것도 실행 파일이 실제로 사용하고있는 메모리 양을 나타내는 신뢰할 수있는 지표가 아니며 메모리 누수를 디버깅하는 데 실제로 적합한 값은 없다는 것입니다.

개인 바이트 는 프로세스 실행 파일이 요청한 메모리의 양을 의미하며 반드시 실제로 사용 하는 양은 아닙니다 . 메모리로 매핑 된 파일 (예 : 공유 DLL)을 (일반적으로) 제외하기 때문에 "비공개"입니다. 그러나 여기에 캐치가 있습니다 . 파일에 의해 할당 된 메모리를 반드시 배제 할 필요는 없습니다 . 개인 바이트의 변경이 실행 파일 자체에 의한 것인지 또는 링크 된 라이브러리에 의한 것인지를 알 수있는 방법은 없습니다. 개인 바이트도 독점적으로 실제 메모리가 아닙니다 . 디스크 또는 대기 페이지 목록으로 페이징 될 수 있습니다 (즉, 더 이상 사용되지 않지만 아직 페이징되지 않음).

작업 집합 은 프로세스에서 사용 하는 총 실제 메모리 (RAM)를 나타냅니다 . 그러나 개인 바이트와 달리 여기에는 메모리 매핑 파일 및 기타 다양한 리소스가 포함되므로 개인 바이트보다 측정 정확도가 떨어집니다. 이것은 작업 관리자의 "Mem Usage"에보고 된 것과 동일한 값이며 최근 몇 년 동안 끝없는 혼란의 원천이었습니다. 작업 세트의 메모리는 페이지 결함없이 처리 될 수 있다는 점에서 "물리적"입니다. 그러나, 대기 페이지 목록입니다 또한 물리적으로 메모리에 있지만 작업 집합에보고, 당신은 응용 프로그램을 최소화 할 때 갑자기 드롭 "메모리 사용"을 볼 수 있습니다 이유입니다.

가상 바이트 는 전체 프로세스가 차지하는 총 가상 주소 공간 입니다. 이것은 메모리 매핑 된 파일 (공유 DLL)을 포함한다는 점에서 작업 세트와 비슷하지만 대기 목록의 데이터와 이미 페이징 된 데이터와 디스크의 페이지 파일에있는 데이터도 포함합니다. 로드가 많은 시스템의 모든 프로세스에서 사용하는 총 가상 바이트는 머신의 실제 메모리보다 훨씬 많은 메모리를 추가합니다.

관계는 다음과 같습니다.

  • 프라이빗 바이트는 앱이 실제로 할당 한 것이지만 페이지 파일 사용량을 포함합니다.
  • 작업 세트는 비 페이징 개인 바이트와 메모리 매핑 파일입니다.
  • 가상 바이트는 작업 세트와 페이징 된 개인 바이트 및 대기 목록입니다.

여기 또 다른 문제가 있습니다. 그냥 공유 라이브러리는 잠재적 인 오탐 (false positive)로 이어지는 응용 프로그램 모듈 내부 메모리를 할당 할 수 있습니다 앱의 전용 바이트에보고, 당신 또한 내부 메모리를 할당 끝낼 수 있습니다 응용 프로그램 공유 false로 이어지는, 모듈 제외 . 즉, 실제로 응용 프로그램에서 개인 바이트에 절대로 나타나지 않는 메모리 누수가 발생할 수 있습니다. 가능하지는 않지만 가능합니다.

개인 바이트는 실행 파일이 사용중인 메모리의 대략적인 근사치 이며 메모리 누수 가능성이있는 후보 목록을 좁히는 데 사용할 수 있습니다 . 지속적으로 그리고 끊임없이 숫자가 증가하고 증가하는 것을 볼 경우 해당 프로세스에서 누수가 있는지 확인하고 싶을 것입니다. 그러나 이것은 누출이 있음증명할 수 없습니다 .

Windows에서 메모리 누수를 감지 / 수정하는 가장 효과적인 도구 중 하나는 실제로 Visual Studio입니다 (링크는 제품 페이지가 아니라 메모리 누수를 위해 VS를 사용하는 페이지로 이동 함). 합리적인 정화 는 또 다른 가능성입니다. 또한 Microsoft는 이 주제에 대한보다 일반적인 모범 사례 문서 를 보유하고 있습니다 . 이 이전 질문 에 더 많은 도구가 나열되어 있습니다.

이것이 몇 가지 사항을 해결하기를 바랍니다. 메모리 누수를 추적하는 것은 디버깅에서 가장 어려운 작업 중 하나입니다. 행운을 빕니다.


26
나는 당신이 대답하는 것이 옳지 않다는 것을 두려워합니다. 개인 바이트는 실제 메모리뿐만 아니라 프로세스 실행 파일이 요청한 메모리 양 (RAM)을 나타냅니다. 따라서 개인 바이트를 모니터링하여 대부분의 메모리 누수 사례를 검사 할 수 있습니다. :: VisualAlloc을 사용하여 많은 양의 메모리 (예 : 1.5G)를 커밋하십시오. 개인 바이트가 작업 세트보다 훨씬 크다는 것을 알 수 있습니다. "작업 집합은 개인 바이트 + 메모리 매핑 파일입니다"가 잘못되었음을 나타냅니다.
Jay Zhu

4
실제로, 나는 쓰기 이해가 "작업 세트는 메모리 내 개인 바이트 + 메모리 매핑 파일"이라고 믿습니다. 개인 바이트는 스왑 아웃 될 수 있습니다. 머신에있는 실제 메모리보다 개인 바이트가 더 큰 것을 볼 수 있습니다.
Jay Zhu

2
@Aaronaught : 신뢰할 수있는 표시기 및 디버깅에 적합한 첫 번째 진술은 혼동됩니다. 개인 바이트는 응용 프로그램 메모리 공간 누출의 신뢰할 수있는 표시기입니다. 종속 DLL 및 간접적 일 수 있지만 응용 프로그램 메모리 공간에서 누출입니다. 디버깅에 사용할 수없는 이유를 설명 할 수 있습니까? 응용 프로그램 프로세스의 전체 메모리 덤프는이 메모리를 사용하는 대상을 알려줍니다. 왜 디버깅에 사용할 수 없는지 잘 모르겠습니다. 약간의 빛을 비출 수 있습니까?
G33kKahuna

@ G33kKahuna : "무엇"이 "어떤 모듈"을 의미하지 않는 한, 메모리 덤프가 어떤 의미의 의미로 메모리를 소비하고 있는지를 어떻게 알 수 있는지는 확실하지 않습니다. 시간이 지남에 따라 엄격하게 제어되는 조건에서 여러 덤프를 수행하지 않는 한 시간이 지남에 따라 실제로 메모리가 누수되는 모듈. 보다 비효율적이고 신뢰할 수없는 디버깅 전략을 생각하기는 어렵습니다. 오늘날 프로파일 러는 어디에나 있습니다. 하나를 사용하십시오.
Aaronaught

1
전체! objsize를 실행하면 즉시 힙에 고정 된 오브젝트가 표시됩니다. eeheap -gc를 확인하여 확인할 수 있습니다. 볼륨이 걸린 부분이 표시됩니다. 일반적으로 위의 모든 명령에서 힌트를 사용할 수없는 경우 개인 바이트는 GC의 수집되지 않은 객체에 의해 소비됩니다. 이제 gchandles 또는 gcleaks로 이동하십시오. 이 명령은 매핑 할 수없는 유형 / 객체 주소를 알려줍니다. 포인터가 여전히 있지만 개체가 사라졌습니다. 이것은 릴리스되지 않은 이벤트 핸들러에 대한 범주적인 문제점입니다.
G33kKahuna

10

perfmon, 작업 관리자 또는 이와 유사한 도구를 사용하여 메모리 누수를 확인해서는 안됩니다. 트렌드를 식별하는 데는 좋지만 다른 것은 아닙니다. 그들이 절대 용어로보고하는 숫자는 너무 모호하고 집계되어 메모리 누수 감지와 같은 특정 작업에 유용하지 않습니다.

이 질문에 대한 이전 답변은 다양한 유형이 무엇인지에 대한 훌륭한 설명을 제공했습니다.

도구 권장 사항에 대해 묻습니다. Memory Validator를 권장합니다. 수십억 개의 메모리 할당을 수행하는 응용 프로그램을 모니터링 할 수 있습니다.

http://www.softwareverify.com/cpp/memory/index.html

면책 조항 : Memory Validator를 설계했습니다.


1
간단한 클래스 파일 (Java)을 실행할 수도 없습니까? 무엇을 제공합니까?
jn1kk

나는 Stephen과 Devil이 어떻게 든 관련이 있거나 복제 된 것으로 의심됩니다 ... : D;)
Robert Koritnik

@StephenKellett, 평가판이 있습니까?
Pacerier

@Pacerier 링크를 따라 가면 페이지 왼쪽의 구매 옵션 바로 위에있는 x86 및 x64 버전 모두에 대한 평가판이 있습니다.
Bradley A. Tetreault

10

perfmon 카운터의 정의는 처음부터 깨졌으며 어떤 이유로 수정하기가 너무 어려워 보입니다.

Windows 메모리 관리에 대한 좋은 개요는 MSDN의 " 메모리 관리 미스테리 공개 " 비디오에서 볼 수 있습니다 . 메모리 누수를 추적하는 데 필요한 것 (예 : 작업 세트 관리)보다 더 많은 주제를 다루지 만 관련 항목에 대해서는 충분히 자세히 설명합니다.


perfmon 카운터 설명에 대한 문제점에 대한 힌트를 제공하기 위해 MSDN의 " Private Bytes Performance Counter-Beware! "의 개인 바이트에 대한 내부 기사는 다음과 같습니다.

Q : 개인 바이트는 개인 바이트가 아닌 경우는 언제입니까?

A : 상주하지 않을 때.

Private Bytes 카운터는 프로세스의 커밋 요금을보고합니다. 즉, 스왑 파일이 스왑 아웃 된 경우 개인 메모리의 내용을 보유하기 위해 스왑 파일에 할당 된 공간의 양입니다. 참고 : 나는 예약되지 않은 상태에서 가상 메모리와 혼동 될 수 있기 때문에 "예약 됨"이라는 단어를 피하고 있습니다.


MSDN의 " 성능 계획 "에서 :

3.3 개인 바이트

3.3.1 설명

개인용 메모리는 다른 프로세스와 공유 할 수없는 프로세스에 할당 된 메모리로 정의됩니다. 이 메모리는 여러 프로세스가 머신에서 실행될 때 공유 메모리보다 비쌉니다. (전통적인) 관리되지 않는 dll의 개인 메모리는 일반적으로 C ++ 정적으로 구성되며 dll의 전체 작업 집합의 5 % 정도입니다.


1
그것이 어떻게 깨지는 지에 대한 미친 좋은 예 때문에 투표하십시오!
Bruno Brant

첫 번째 인용은 착각이다. "비공개 바이트"를 할당 할 때는 "스왑 파일에 할당"(실제로는 페이지 파일이라고 함)이 필요하지 않습니다. "개인 바이트"를 할당하기위한 페이지 파일이 없어도됩니다. 사실, 개인 바이트를 할당 즉시 사용하지 않는 모든 공간 어디서나 , 그리고만큼 할당 된로 지금까지 사용할 수 없습니다.
Jamie Hanrahan

두 번째 인용문은 그리 좋지 않습니다. DLL 코드에 사용 된 개인 바이트는 반드시 DLL 내에 정적으로 할당 될 필요는 없습니다. DLL 코드는 VirtualAlloc, HeapAlloc (malloc 및 CRTL의 새로운 기능) 등을 완벽하게 호출 할 수 있습니다. 또한 개인 메모리 크기를 작업 세트 크기의 백분율로 설명하려고합니다. 전자는 가상 크기이며 (동일한 입력으로 코드를 사용할 때마다 동일) 후자는 물리적입니다 (메모리가 많거나 많은 양에 따라 실행마다 크게 다를 수 있음) 기계가 굶주 렸습니다).
Jamie Hanrahan

5

흥미로운 토론이 여기에 있습니다 : http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ 이 스레드의 나의 이해는 해방 작은 할당이 있다는 것입니다 개인 바이트 또는 작업 세트에 반영되지 않습니다.

간단히 말해 :

내가 전화하면

p=malloc(1000);
free(p);

프라이빗 바이트는 할당 해제가 아닌 할당 만 반영합니다.

내가 전화하면

p=malloc(>512k);
free(p);

그런 다음 개인 바이트는 할당 및 할당 해제를 올바르게 반영합니다.


7
이는 C 표준 라이브러리 메모리 기능이 하위 수준 프로세스 수준 메모리 관리의 상단에있는 메모리 관리 메커니즘 인 사용자 지정 또는 Win32 힙을 사용한다는 사실에 의해 설명됩니다.
Kyberias 2016 년

@Kyberias, 그래서 우리는 어떻게 그 아래 에 도달 합니까?
Pacerier

동안 (1) 자유 (malloc (1000)); // Private Bytes가 영원히 증가합니까?
franckspike

2
@franckspike : 아니오, CRT가 OS에서 새 페이지를 요청하는 대신 이전에 사용 가능한 메모리를 다시 사용하기 때문에 특정 지점 (일반적으로 약 4kB이지만 다양 할 수 있음)으로 증가한 다음 중지됩니다.
Miral

@Pacerier : VirtualAlloc 및 VirtualFree에 전화 할 수 있습니다.
Jamie Hanrahan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.