짧은 답변
"메모리 부족"팝업에 개인 커밋 메모리 (가상 메모리 유형) 에 대한 한계가 부족하다고 말합니다 . RAM (실제 메모리)이 부족하지는 않습니다. 사용 가능한 RAM 용량은 중요하지 않습니다 . 사용 가능한 RAM이 많으면 커밋 제한을 초과 할 수 없습니다. 커밋 제한은 총 RAM (사용 여부에 관계없이)과 현재 페이지 파일 크기의 합입니다.
반대로, "사용하는"커밋 제한 (주로 프로세스 전용 가상 주소 공간 생성)은 반드시 RAM을 사용할 필요는 없습니다! 그러나 OS는 필요할 때 저장해야 할 장소가 없다는 것을 알지 못하면 생성을 허용하지 않습니다. 따라서 모든 RAM 또는 대부분의 RAM을 사용하지 않고도 커밋 제한에 도달 할 수 있습니다.
따라서 페이지 파일없이 실행하지 않아야합니다. 페이지 파일이 실제로 쓰여지지 않을 수도 있습니다! 그러나 여전히 "메모리 부족"및 "메모리 부족"오류를 방지 할 수 있습니다.
중급 답변
Windows에는 실제로 RAM이 부족하다는 오류 메시지가 없습니다. 부족한 것은 "커밋 한도"입니다.
해당 버전의 Process Explorer에서 "시스템"그래프 이름이 잘못되었습니다. "충전 요금"으로 표시되어야합니다. (버전에서는 "시스템 커밋"이라고합니다. 더 좋지만 여전히 완전히 일관성이 없습니다.) 어쨌든 그래프의 "현재"높이는 텍스트 섹션에서 "Commit Charge"- " Current "및 그래프의 최대 높이는"Commit Charge "-"Limit "를 나타냅니다.
"커밋 요금"은 페이지 파일 (있는 경우)이 지원하는 가상 주소 공간을 의미합니다. 즉, RAM에 모두 맞지 않을 경우 나머지는 페이지 파일로 이동합니다. ( "매핑 된"vas라고하는 다른 파일에 의해 백업되거나 항상 RAM에 남아 있어야하는 다른 유형의 vas가 있습니다. 후자는 "nonpageable"이라고합니다. "commit limit"은 최대 값입니다. "약속 요금"이 될 수 있습니다. RAM 크기에 페이지 파일 크기를 더한 것과 같습니다.
커밋 한계가 RAM 크기와 같기 때문에 페이지 파일이 없기 때문에 커밋 한계는 단순히 RAM 크기입니다.
분명히 다양한 프로그램 + OS가 거의 모든 가능한 커밋을 사용했습니다.
이것은 사용 가능한 RAM의 양이나 사용 가능한 RAM의 양과 직접적인 관련이 없습니다. 예, 약 4.5GB의 RAM을 사용할 수 있습니다. 커밋 한계를 초과 할 수있는 것은 아닙니다. 커밋 된 메모리는 반드시 RAM을 사용할 필요는 없으며 사용 가능한 RAM의 양에 의해 제한되지 않습니다.
페이지 파일을 다시 활성화해야합니다.이 많은 커밋을 사용하면 16GB 페이지 파일을 제안합니다 .OS에서 많은 양의 RAM을 RAM에 보관하지 않도록하고 페이지 파일이 가장 잘 작동하기 때문입니다. 여유 공간이 많거나 RAM을 더 추가하십시오. 더 많은. 좋은 성능을 위해서는 페이지 파일이 지원하지 않는 코드 및 기타 자료를위한 RAM 공간이 충분해야합니다 (하지만 다른 파일로 페이징 될 수 있음).
매우 긴 답변
(그러나 여전히 Windows Internals 의 메모리 관리 장보다 훨씬 짧습니다 ...)
프로그램이 100MB의 프로세스 전용 가상 메모리를 할당한다고 가정합니다. 이것은 "commit"옵션을 가진 VirtualAlloc 호출로 수행됩니다. "Commit charge"가 100MB 증가합니다. 그러나이 "할당"은 실제로 어떤 RAM도 사용하지 않습니다! RAM은 새로 커밋 된 가상 주소 공간 중 일부에 처음 액세스 할 때만 사용됩니다 .
RAM이 결국 어떻게 사용 되는가
(그렇다면)
새로 커밋 된 공간에 처음으로 액세스하면 거의 항상 메모리 쓰기가됩니다 (쓰기 전에 새로 할당 된 개인용 VA를 읽는 것은 초기 내용이 엄격하게 말해서 정의되지 않기 때문에 거의 항상 프로그래밍 오류입니다). 그러나 새로 할당 된 vas 페이지를 처음 만질 때 읽거나 쓰는 결과는 페이지 오류 입니다. "fault"라는 단어는 나쁘게 들리지만 가상 메모리 OS에서 페이지 오류는 완전히 예상되는 이벤트입니다.
이 특정 유형의 페이지 결함에 대한 응답으로, 호출기 (OS 메모리 관리자의 일부이며, 때때로 "Mm"으로 표시)는 다음과 같습니다.
- RAM의 물리적 페이지를 할당합니다 (이상적으로는 제로 페이지 목록에서 시작하지만, 어떤 경우 든 Windows는 "사용 가능"이라고합니다) : 선호하는 순서대로 0, 사용 가능 또는 대기 페이지 목록.
- 실제 페이지를 가상 페이지와 연관시키기 위해 페이지 테이블 항목 을 채우십시오 . 그리고 마지막으로
- 페이지 결함 예외를 해제하십시오.
그 후 메모리 참조를 수행 한 코드는 페이지 오류를 일으킨 명령어를 다시 실행하고 이번에는 참조가 성공합니다.
페이지가 프로세스 작업 세트와 RAM에 "고장났다"고합니다. 작업 관리자에서 이는 프로세스의 "개인 작업 세트"에서 한 페이지 (4KB) 증가한 것으로 나타납니다. 사용 가능한 실제 메모리가 한 페이지 줄어 듭니다. 후자는 사용량이 많은 컴퓨터에서는 알아 채기가 어려울 수 있습니다.
참고 1 : 이 페이지 결함에는 디스크에서 읽은 내용이 없습니다. 커밋 된 가상 메모리의 절대 액세스 할 수없는 페이지는 디스크에서 수명을 시작하지 않습니다. 그것을 읽을 수있는 디스크 곳이 없습니다 에서를 . 이전에 사용 가능한 RAM 페이지에서 "구체화"되었습니다. 실제로, 대부분의 페이지 결함은 RAM에서 다른 프로세스를 위해 이미 RAM에있는 공유 페이지 또는 페이지 캐시 (대기 또는 수정 된 목록) 또는 이와 같은 "필요한 0"페이지로 해결됩니다.
참고 2 : "사용 가능"페이지에서 4096 바이트 한 페이지 만 가져옵니다. 커밋되지 않은 주소 공간은 일반적으로 각 페이지가 처음으로 "터치"되므로 일반적으로 한 번에 한 페이지 만 실현됩니다. 한 번에 더 많은 일을하는 데에는 개선이나 이점이 없습니다. n 배나 길어요 반대로 디스크에서 페이지를 읽어야하는 경우 디스크 읽기에서 대부분의 시간이 실제 데이터 전송이 아니라 작업 별 오버 헤드에 있기 때문에 일정량의 "선독"이 시도됩니다. "커밋 된"양은 100MB로 유지됩니다. 하나 이상의 페이지에 결함이 있다는 사실은 커밋 요금을 줄이지 않습니다.
노트 3:4GB "사용 가능한"RAM이 있다고 가정합니다. 즉, RAM이 부족하기 전에 이미 할당되었지만 결코 참조되지 않은 커밋 된 메모리를 약 백만 번 (4GB / 4096) 참조 할 수 있습니다. 이 시점에서 David Cutler와 Lou Perazzoli가 의도 한대로 페이지 파일이있는 경우 RAM에서 가장 긴 참조 페이지는 디스크에 저장되고 이러한 최신 페이지 결함을 해결하는 데 사용할 수있게됩니다. (실제로 OS는 그 전에 "작업 세트 트리밍"과 같은 RAM 교정 방법을 시작하며 페이지 파일에 대한 실제 쓰기는 효율성을 위해 수정 된 페이지 목록에 캐시되고 배치되며, ...) "커밋 된"수 그러나 "커밋 제한"과 관련이 있습니다. "공간이 모두없는 경우"
그리고 그것은 계속 일어나고 있습니다 ...
그러나 백만 건의 참조를 더 이상 수행하지 않았으며 여전히 "사용 가능한"약 4GB의 페이지가 있다고 가정 해 봅시다. 이제 동일한 프로세스 (또는 다른 문제는 중요하지 않음)가 다른 VirtualAlloc을 수행한다고 가정하겠습니다. 이번에는 200MB가 커밋되었습니다. 이 200MB는 커밋 요금에 추가되며 사용 가능한 RAM을 제거하지 않습니다. 단순히 VirtualAlloc'ating 주소 공간은 해당하는 양의 RAM을 사용하지 않으며 "사용 가능한"RAM이 적더라도 VirtualAlloc이 사용할 수있는 주소 공간의 양을 제한하지 않습니다 (높은 가용 RAM도 증가하지 않음).
(글쎄, 알았어 ... PAE가 아닌 x86의 x86 인 경우 4MB마다 페이지 테이블에 사용되는 하나의 (페이지 가능) 페이지에 약간의 오버 헤드가 있습니다. 가상 주소 공간이 할당되어 있으며 가상으로 할당 된 각 범위에 대해 수십 바이트의 "가상 주소 설명자"가 있습니다.)
이런 식으로 가능하며 일반적입니다! -소량의 RAM 만 사용하면서 많은 "커밋 요금"을 사용합니다.
따라서 "커밋"가상 주소 공간이 RAM을 사용하지 않는다면 왜 제한이 필요한가?
"커밋 요금"은 향후 스토리지 공간 사용 가능성을 나타냅니다 . "커밋 한도"는 이러한 할당을 실제로 보유 할 수있는 총 스토리지 용량 (RAM + 페이지 파일 공간)을 나타냅니다 .
Mm이 VirtualAlloc 요청을 승인하면 할당 된 영역에 대한 모든 후속 메모리 액세스가 성공할 것으로 약속합니다 ( "약속"). 페이지 결함이 발생할 수 있지만 RAM 또는 페이지 파일에 상관없이 모든 페이지의 컨텐츠를 보관할 수있는 충분한 스토리지가 있기 때문에 결함을 모두 해결할 수 있습니다. Mm은 저장 공간이 얼마인지 (커밋 한계), 이미 "커밋 된"크기 (현재 커밋 요금)를 알고 있기 때문에 이것을 알고 있습니다.
(그러나 이러한 모든 페이지에 아직 액세스 할 필요는 없었으므로 주어진 시간에 커밋 된 양에 따라 실제 스토리지가 반드시 필요한 것은 아닙니다.)
그래서 ... "시스템의 메모리가 부족합니다"는 어떻습니까?
VirtualAlloc을 시도하고 현재 커밋 요금에 요청 된 할당 크기를 더한 경우 커밋 한계를 초과하게되고 OS가 커밋 한계를 높이기 위해 페이지 파일을 확장 할 수없는 경우 "메모리 부족"팝업이 나타납니다. 프로세스에 VirtualAlloc 호출 FAIL이 표시됩니다. 대부분의 프로그램은 손을 내밀고 그 시점에서 죽습니다. 어떤 사람들은 전화가 성공했다고 가정하고 맹목적으로 압박하고, 그들이 할당했다고 생각한 지역을 참조하려고 할 때 나중에 실패합니다.
다시 한 번 (반복 죄송합니다) 사용 가능한 RAM의 양은 중요하지 않습니다. OS는 RAM 또는 페이지 파일 공간 이 필요할 때 사용할 수 있다고 약속했지만 그 약속은 "사용 가능"에서 제외되지 않습니다. 사용 가능한 RAM은 커밋 된 vm 이 처음 참조 될 때만 사용되며 , 이는 "고장"(즉, 실제 메모리에서 실현)되는 원인이됩니다. 그리고 단순히 가상 메모리를 커밋 (= 할당)해도 그렇게하지 않습니다. 사용 가능한 가상 주소 공간 만 사용하고 가상 주소 공간을 사용 가능하게 만듭니다.
그러나 "메모리 부족"의 경우 커밋 된 메모리에 대한 할당 요청이 있었고 OS가 현재 커밋 요금을이 새로운 요청의 크기에 추가 했으며 총합이 커밋 제한 보다 큰 것으로 나타났습니다 . OS가이 새로운 하나를 승인, 그래서 경우 와 공간이 그 후 참조 된 모든 것을, 모든 것을 저장하는 실제 장소 (RAM + 페이지 파일)가 없을 것입니다.
OS는 이것을 허용하지 않습니다. 최악의 경우를 유지하기위한 공간보다 더 많은 vas를 할당 할 수 없습니다. 모든 "fault in"상태 일지라도 말입니다. 이것이 "커밋 한계"의 목적입니다.
나는 세 번 당신에게 세 번 당신에게 세 번 말해 당신에게 : "사용 가능한"RAM의 양은 중요하지 않습니다. 커밋 된 가상 공간이 실제로 해당 스토리지 공간을 모두 사용하고 있지는 않습니다. Windows는 향후에 모두 오류가 발생하지 않는 한 가상 할당에 "커밋"할 수 없습니다.
코드와 대용량 데이터 파일에 액세스하는 데 주로 사용되는 "매핑 된"이라는 다른 유형의 vas가 있지만 "commit charge"에 청구되지 않으며 "commit limit"에 의해 제한되지 않습니다. 자체 저장 영역과 함께 "매핑 된"파일이 제공되기 때문입니다. "매핑 된"vas의 유일한 제한은 매핑 된 파일에 대한 디스크 공간과 프로세스에서 파일을 매핑 할 수있는 사용 가능한 va의 양입니다.
그러나 시스템을 볼 때 아직 커밋 한계에 도달하지 않았습니까?
기본적으로 측정 및 기록 유지 문제입니다. VirtualAlloc 호출이 이미 시도되고 실패한 후 시스템을보고 있습니다.
커밋 제한이 500MB에 불과하고 일부 프로그램이 VirtualAlloc 600MB를 시도했다고 가정합니다. 시도가 실패합니다. 그런 다음 시스템을보고 "뭐? 아직도 500MB가 남았습니다!"라고 말합니다. 실제로 문제가 발생한 프로세스가 그 시점까지 완전히 사라졌기 때문에 이전에 할당 된 커밋 된 메모리가 모두 해제되었으므로 실제로 훨씬 더 남을 수 있습니다.
문제는 당신이 시간을 되돌아보고 할당 시도가 이루어진 순간 커밋 요금 이 무엇인지 볼 수 없다는 것 입니다. 그리고 당신은 시도가 얼마나 많은 공간을 알지 못합니다. 따라서 시도가 실패한 이유 또는 작동을 허용하기 위해 얼마나 많은 "커밋 제한"이 필요한지 알 수 없습니다.
나는 "시스템이되어 본 적이 부족 메모리를". 그게 뭐야?
위의 경우 OS가 페이지 파일을 확장 할 수있는 경우 (즉, 기본 "시스템 관리"설정으로 유지하거나 관리하지만 최대 값을 초기 값보다 크게 설정하고 디스크 여유 공간이 충분 함) 및 이러한 확장은 VirtualAlloc 호출이 성공할 수 있도록 커밋 한계를 충분히 증가시킨 다음 Mm이 페이지 파일을 확장하고 VirtualAlloc 호출이 성공합니다.
그리고 "시스템의 메모리가 부족합니다"라는 메시지가 나타납니다. 이는 완화없이 상황이 지속되면 곧 "메모리 부족"경고가 표시 될 것이라는 조기 경고입니다. 일부 앱을 종료 할 시간입니다. 브라우저 창부터 시작하겠습니다.
그게 좋은 것 같아요? 페이지 파일 확장은 악하다 !!!
아닙니다. OS는 실제로 기존 파일을 "확장"하지 않습니다. 새로운 범위를 할당합니다. 효과는 다른 비 연속 파일과 매우 유사합니다. 이전 페이지 파일 내용은 그대로 유지됩니다. 새로운 장소 나 다른 곳에 복사 할 필요가 없습니다. 대부분의 페이지 파일 IO는 페이지 파일 크기에 비해 상대적으로 작은 청크로 구성되어 있기 때문에 주어진 전송이 범위 경계를 넘을 가능성은 매우 드물기 때문에 조각화는 너무 과도하지 않으면 크게 아프지 않습니다.
마지막으로, 확장에 "커밋 된"공간이있는 모든 프로세스가 종료되면 (빠르지 않은 경우 OS 종료시) 익스텐트가 자동으로 해제되고 페이지 파일이 이전 크기 및 할당으로 돌아갑니다. 다시 그렇습니다.
따라서 페이지 파일 확장을 허용하면 완전 무료 안전망 역할을합니다. 허용하지만 시스템에서이를 필요로하지 않는 경우 시스템은 자주 요구되는대로 "페이지 파일을 지속적으로 확장 및 축소"하지 않으므로 비용이 들지 않습니다 . 그리고 필요한 경우 "가상 메모리 부족"오류로 인해 앱이 중단되는 것을 방지합니다.
하지만하지만 ...
수십 개의 웹 사이트에서 페이지 파일 확장을 허용하면 Windows가 페이지 파일을 지속적으로 확장 및 축소하여 조각 모음을 수행 할 때까지 페이지 파일이 조각화된다는 내용을 읽었습니다.
그들은 단지 틀렸다.
"메모리 부족으로 실행"(또는 이전 버전에서 "가상 메모리 부족으로 실행") 팝업을 본 적이 없다면 OS가 페이지 파일을 확장하지 않은 것입니다.
해당 팝업이 표시되면 초기 페이지 파일 크기가 너무 작음을 나타냅니다. (최대 관찰 사용량의 약 4 배로 설정하고 싶습니다. 즉 "% pagefile 사용량 피크"perfmon 카운터는 25 % 미만이어야합니다. 이유 : 페이지 파일 공간은 다른 힙과 같이 관리되며 많은 여유 공간에서 가장 잘 작동합니다. 게임을하세요.)
하지만 왜 그냥 ...
OS가 할당을 허용 한 다음 페이지 결함을 해결하는 데 사용 가능한 RAM이 없으면 참조가 실패 하도록해야한다고 주장 할 수 있습니다. 즉, 우리는 초기 페이지 오류 작품, 어떤 경우 가능한 없었다 때문에 (1 단계) 할 수 없습니다 "RAM의 사용 가능한 물리적 페이지를 할당"방법을 설명하는 위까지 와 곳은 없었다 사용할 수 있도록 페이지를 남겼습니까?
그러면 호출기가 페이지 결함을 해결할 수 없습니다. 예외 (페이지 오류)가 오류 스레드로 다시보고되도록해야하며 다른 예외 코드로 변경되었을 수 있습니다.
설계 철학은 커밋 한계가 부족한 경우 VirtualAlloc이 주소 대신 0 (기술적으로 NULL 포인터)을 반환하며 프로그래머가 VirtualAlloc 호출이 실패 할 수 있음을 예상하는 것이 합리적이라는 것입니다. 따라서 프로그래머는 해당 사례를 확인하고 이에 대한 합리적인 조치를 취해야합니다 (예 : 해당 시점까지 작업을 저장 한 다음 프로그램을 "정직하게"종료 할 수있는 기회). (프로그래머 : malloc, new 등에서 NULL 포인터 리턴을 확인합니까? 그렇다면 왜 그렇지 않습니까?)
그러나 프로그래머는 간단한 메모리 참조와 같은 것을 기대할 필요는 없습니다.
i = 0; // initialize loop counter
주소 공간이 성공적으로 커밋 된 영역에 있지 않으면 실패 할 수 있습니다. (또는 그 문제에 대해 매핑 된 주소 공간) 그러나 "과도하게 할당 된 할당 허용, 메모리 참조 실패"철학을 따른다면 이런 일이 발생할 수 있습니다.
불행히도, 위 코드 줄에서와 같은 메모리 참조는 나쁜 상태를 반환하는 편리한 방법이 없습니다! 그들은 더하기와 빼기처럼 그냥 작동 해야합니다 . 이러한 실패를보고하는 유일한 방법은 예외입니다. 따라서이를 처리하기 위해 프로그래머는 전체 프로그램을 예외 처리기로 래핑해야합니다. (시도 ... 잡아라.)
그렇게 할 수 있습니다 ... 그러나 처리기에서 예외에 대한 응답으로 "올바른 일을하는"방법을 아는 것은 어려울 것입니다. (특히 스택은 VirtualAlloc'd이기 때문에 VirtualAlloc의 메모리, malloc 또는 new로 할당 된 메모리 및 모든 로컬 변수에 대한 모든 메모리 참조 에서 발생할 수 있습니다 .)
요컨대,이 경우 프로그램을 정상적으로 실패하게 만드는 것은 매우 어려울 것입니다.
반면 VirtualAlloc (또는 malloc 또는 new, 정확히 동일하지는 않지만)에서 NULL 포인터 반환을 확인한 다음 합리적인 시도를 수행하는 것은 매우 쉽습니다. 가상 공간에 필요한 프로그램이 무엇이든 할 수 있습니다. 그리고 사용자에게 지금까지 작업을 저장할 것인지 묻습니다 (있는 경우). (물론 너무 많은 앱은 그렇게 많은 일을 신경 쓰지 않습니다.)
커밋의 다른 사용자
또한, "커밋 한계"는 페이징 및 비 페이징 풀, PFN 목록 등과 같은 OS의 다양한 할당에 의해 줄어들지 않습니다. 이런 일이 발생하면 요금이 부과됩니다. 커밋 충전 또는 커밋 제한도 비디오 RAM 또는 비디오 RAM "창"크기의 영향을받지 않습니다.
직접 테스트
SysInternals 사이트에서 testlimit 도구를 사용하여이 모든 것을 데모 할 수 있습니다. 옵션 -m은 커밋 된 주소 공간을 할당하지만 "터치"하지 않으므로 RAM을 할당하지 않습니다. 옵션 -d는 페이지를 할당하고 참조하므로 커밋 요금이 증가하고 사용 가능한 RAM이 줄어 듭니다.
참고 문헌
Russinovich, Solomon 및 Ionescu의 Windows 내부 . testlimit 도구를 사용하여 이러한 모든 사항을 증명할 수있는 데모도 있습니다. 그러나 이것이 오래되었다고 생각되면 경고해야합니다. Mm 장만 200 페이지입니다. 위는 매우 단순화 된 버전입니다. (소개의 "확인"섹션을 참조하십시오.)
MSDN VirtualAlloc 설명서 도 참조하십시오