프로세스에 사용 가능한 메모리 양을 어떻게 제한 할 수 있습니까?


11

진행중인 프로그램을 개발 중입니다. 때때로 매우 많은 양의 메모리 (8G의 실제 메모리가있는 머신에서 >> 10G)가 할당되어 시스템이 응답하지 않게됩니다. 프로세스가 할당 할 수있는 메모리 양을 제한하고 싶습니다. 내가하는 일반적인 방법은 다음과 같습니다.

ulimit -m 4000000 ; ./myprogram

... 4GB 이상의 메모리를 사용하려고하면 프로그램을 종료해야합니다.

OS X El Capitan에서 이것은 효과가없는 것으로 보입니다. 심지어 ulimit -m 1(모든 프로그램을 단지 1kB의 메모리로 제한하는) 효과는 없습니다.

특정 프로세스에 사용 가능한 메모리의 상한을 설정하는 방법은 무엇입니까?


당신이 말할 때 일반적인 방법은 내가 무엇을 의미합니까? 보다 구체적으로, 당신은 일반적으로이 작업을 수행합니까? 그리고 당신이 그것을 할 때, 당신은 Mac OS X El Capitan 또는 다른 환경에서 의미합니까? 당신이 그것을 성공적으로 사용한 예를 줄 수 있습니까? 기본적 으로이 프로세스가 정상적으로 작동하는지 명확하게하려고하지만이 특정 프로그램에서는 작동하지 않습니까? 아니면 전혀 효과가 없지만 생각해야합니까?
Monomeeth

1
"내가하는 평소의 방법"이란 다른 유닉스의 맛에서 이것을하는 방법을 의미합니다. 방금 ulimit -m더 이상 Linux (> 2.4.30)에서 ulimit -v작동하지 않지만 여전히 예상대로 작동 한다는 것을 알았습니다 . (마찬가지로 ulimit -m, ulimit -vOS X에도 영향을 미치지 않는 것으로 보입니다.)
cpcallen

작성중인 프로그램에서 메모리 누수가 발생하여 더 나은 가비지 수집이 필요한 것처럼 들립니다. 메모리 관리에 대해 읽어 보셨습니까?
Todd Dabney

1
아니요, 메모리 누수가 아니라 잠재적으로 매우 큰 상태 공간에 대한 그래프 검색입니다. 다양한 내부 구조가 너무 커지면 검색을 중단하는 코드를 추가 할 수는 있지만 쉘 하나의 라이너로 동일한 작업을 수행 할 수있을 것으로 기대했습니다 (큰 입력으로 기계가 얽 히지 않도록).
cpcallen

답변:


1

메모리 사용을 제한하는 두 가지 방법이 있습니다 : 사후 사실과 선점. 즉, 프로그램이 너무 커진 후에 프로그램을 종료하려고 시도하거나 처음에는 너무 커지지 않도록 프로그램 할 수 있습니다.

ex post facto 접근법을 고집하는 경우 다음 Bash 스크립트를 사용할 수 있습니다. 이 스크립트는 먼저 processid pid를 사용하는 프로세스가 사용중인 메모리의 양 ( "상주 세트 크기"로 정의 된대로)을 찾고 grep을 사용하여 숫자가 아닌 모든 데이터를 필터링하고 그 양을 변수 n으로 저장합니다. 그런 다음 스크립트는 n이 지정된 x보다 큰지 확인합니다. 그렇다면 processid가 pid 인 프로세스가 종료됩니다.

참고 :

  1. <pid>프로그램의 프로세스 ID로 바꿔야합니다 .
  2. 당신은 대체해야 <x>이 프로그램은 초과하지 않을 RSS = "상주 세트 크기"(즉, 실제 메모리 크기)와 함께.

n=$(ps -<pid> -o rss | grep '[0-9]') if [ $n -gt <x> ]; then kill -9 <pid>; fi

이것을 y 초마다 실행하려면 루프로 묶고 매 반복마다 y 초 동안 기다리라고 지시하십시오. 을 사용하여 비슷한 명령을 작성할 수도 있습니다 top. 시작점은입니다 top -l 1|grep "<pid>"|awk '{print $10}'.

@ kenorb의 대답 은 내 스크립트로 도움이되었습니다.


나는 그 질문에 대답한다고 생각하지만 장기적으로 수동 메모리 할당을 사용하여 선제 적 접근 방식을 취하는 것이 더 나은 프로그래밍 디자인이라고 생각합니다.

첫째, 메모리 사용량이 실제로 문제가됩니까? Go 설명서 에는 다음이 명시되어 있습니다.

Go 메모리 할당자는 할당 영역으로 가상 메모리의 넓은 영역을 예약합니다. 이 가상 메모리는 특정 Go 프로세스에 로컬입니다. 예약은 다른 메모리 프로세스를 박탈하지 않습니다.

여전히 문제가 있다고 생각되면 C 프로그래밍 언어에서와 같이 메모리를 수동으로 관리하는 것이 좋습니다. go는 C로 작성되었으므로 C 메모리 관리 / 할당에 들어가는 방법이있을 것 같았고 실제로 있습니다. 이 github 저장소를 참조하십시오 .

시스템의 표준 C 할당자를 통해 수동 메모리 관리를 수행 할 수 있습니다. 그것은 malloc, calloc의 상단에 얇은 포장지이며 무료입니다. 시스템의 이러한 기능에 대한 자세한 내용은 man malloc을 참조하십시오. 이 라이브러리는 cgo를 사용합니다.

사용 사례는 다음과 같습니다.

왜 이것을 원하십니까?

프로그램이 메모리 부족을 유발하거나 시스템 메모리가 부족한 경우 메모리 할당 및 할당 해제를 수동으로 제어하는 ​​것이 도움이 될 수 있습니다. Go를 사용하면 할당을 제어 할 수 있지만 불필요한 데이터를 명시 적으로 할당 취소 할 수는 없습니다.

이것은 더 나은 장기 솔루션처럼 보입니다.

C (메모리 관리 포함)에 대해 더 배우려면 C 프로그래밍 언어 가 표준 참조입니다.


메모리 사용이 실제로 문제라고 확신합니다. 프로그램이 예기치 않게 실제 메모리 크기보다 2 배 이상 커지면 페이지 스레 싱으로 인해 시스템이 거의 응답하지 않게됩니다. ^ C를 눌렀을 때와 macOS가 마우스 클릭에 대한 응답을 재개 할 때까지 약 1 시간이 걸렸습니다. 그동안 얼지 않았다는 유일한 증거는 하드 드라이브의 조용한 소음이 빠르게 떨리는 것입니다.
cpcallen

이 방법은 실제로는 합리적인 솔루션 일 수 있지만 다윈 이외의 UNIX OS에서 ulimit와 달리 kill 명령을 성공적으로 실행하기에 충분한 메모리를 적시에 할당 할 수 있어야합니다. 커널에 의해 프로세스 크기 제한이 실제로 적용되고 싶습니다.
cpcallen

@cpcallen 일부 검색을 수행하면 "ulimit의 -m 매개 변수가 2.4.30보다 최신 커널 버전을 가진 Linux 시스템에는 영향을 미치지 않습니다." OSX도이 변화를 포착 한 것으로 보입니다. -v 옵션을 사용하여 주소 공간을 제한하십시오
Evan Rosica

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.