리눅스 메모리 조각화


20

리눅스에서 메모리 조각화를 감지하는 방법이 있습니까? 오래 실행되는 일부 서버에서 성능 저하가 나타 났으며 프로세스를 다시 시작한 후에 만 ​​더 나은 성능을 볼 수 있기 때문입니다. 리눅스의 거대한 페이지 지원을 사용할 때 더 많은 것을 알았습니다. 리눅스의 거대한 페이지는 조각화되기 쉽습니다.

특히 / proc / buddyinfo를 살펴 보았습니다. CLI 명령 자체, 프로그램 또는 이론적 배경이 아닌 더 나은 방법이 있는지 확인하고 싶습니다.


나는 간단한 명령 줄 솔루션을 보지 않고 간단한 프로그램 / 이론도 할 것입니다. 따라서 나는 serverfault에 묻지 않았다.
Raghu

1
나는 여기서 한 가지 이해하지 못한다. 내가 이해하는 한 메모리 조각화는 메모리 부족을 초래하고 결과적으로 메모리 할당 오류를 초래해야합니다. 그러나 성능 저하에 대해 묻고 있습니다. 디스크로 스왑 된 메모리가 많기 때문입니까? 그렇다면 vmstat이 분야에서 무엇을 주어야 so합니까?

@skwllsp-더 구체적으로 답변을 편집했습니다.
Tim Post

@Raghu-대부분의 시스템 관리자가 커널 코드를 수정하여 메모리 관리가 다르게 작동하도록 기대하지는 않지만 숙련 된 Linux 관리자는 Linux가 메모리를 관리 하는 방법에 대한 개요를 알아야 합니다. 이 질문은 실제로 진행 중입니다. 귀하의 질문에 답변하는 코드를 제안 할 수 없기 때문에 단순히 마이그레이션하기 위해 투표했습니다. / proc에서 읽거나 사용 vmstat하는 것은 일반적인 사용자 경험입니다. 동일한 작업을 수행 하는 프로그램 을 작성하는 경우 에는 달라집니다. bash를 사용 하여이 정보를 수집하려면 질문을 편집하십시오. 닫히지 않을 것입니다 :)
Tim Post

@Tim-내가 알고 싶었던 bash / cli 명령이 아니라 제안한 결과 벤치마킹 절차에 도움이되는 정보가 필요했습니다 (결과를 분석하지 않고 실행하지 않음).
Raghu

답변:


12

태그에 응답하고 있습니다. 내 대답은 Linux 에만 해당됩니다 .

예, 큰 페이지는 조각화되기 쉽습니다. 메모리에 대한 두 가지보기가 있는데, 하나는 프로세스가 가져오고 (가상) 커널이 관리하는 (실제)입니다. 모든 페이지가 클수록, 특히 서비스가 기본적으로 할당되어 더 많은 메모리에 쓰는 다른 시스템을 지원해야하는 시스템에서 서비스를 실행하는 경우 주변 장치를 그룹화 (및 유지)하기가 더 어려워집니다. 실제로 사용합니다.

커널의 (실제) 부여 된 주소 매핑은 비공개입니다. 커널이 사용자 공간을 혼동하지 않고 오버 커밋 할 수 있어야하기 때문에 사용자 공간이 커널이 제시하는 것으로 사용자 공간을 보는 이유는 매우 좋습니다. 프로세스는 훌륭하고 연속적인 "Disneyfied" 주소 공간을 얻습니다 . 커널이 실제로 메모리 뒤에서 수행하는 작업을 알지 못합니다 .

당신이 오랫동안 실행하는 서버에서 성능 저하를 볼 수있는 이유는 대부분 명시 적으로 고정 (예를 들면되지 않은 할당 된 블록 때문입니다 mlock()/ mlockall()또는 posix_madvise()한 동안 수정)하지가 한 페이지 아웃 읽기가있을 때 디스크에 서비스 스키드을 의미한다, 그들. 이 동작을 수정하면 프로세스가 나쁜 이웃 이되므로 많은 사람들이 RDBMS를 web / php / python / ruby ​​/ whatever와 완전히 다른 서버에 배치합니다. 이 문제를 해결하는 유일한 방법은 인접한 블록에 대한 경쟁을 줄이는 것입니다.

페이지 A가 메모리에 있고 페이지 B가 스왑으로 이동 한 경우에만 조각화가 눈에 able니다 (대부분의 경우). 당연히 서비스를 다시 시작하면 이것을 '치료'하는 것처럼 보이지만 커널이 아직 초과 커밋 비율의 범위 내에서 새로 할당 된 블록 (현재)을 프로세스를 페이징 아웃 할 기회가 없었기 때문입니다.

실제로, 높은로드 상태에서 'apache'를 다시 시작하면 (아파치) 다른 서비스가 소유 한 블록을 디스크로 바로 보낼 수 있습니다. 따라서 'apache'는 짧은 시간 동안 향상되지만 'mysql'은 .. 최소한 충분한 물리적 메모리가 부족할 때 커널이 똑같이 고통을 겪을 때까지 겪을 수 있습니다.

더 많은 메모리를 추가하거나 까다로운 malloc()소비자를 분리하십시오 .

시도 vmstat실제로 어디에 저장되어 있는지에 대한 개요를 얻을 수 있습니다.


응답 해주셔서 감사합니다. mysql-innodb 버퍼 풀에 대해 거대한 페이지 (각각 = 2048KB)를 사용하여 얼마나 잘 처리되는지 확인했습니다 (sysbench 사용). 처음에는 프로세스 가동 시간 (및 심지어 시스템 가동 시간)이 낮을 때 매우 좋은 결과를 얻었습니다. 그러나 여러 번의 실행에서 성능이 저하되기 시작했습니다. 언급 한 페이지와 관련하여 VM 활동이 많이 있음을 분명히 알았지 만 벤치 마크 및 innodb 로그 플러싱 (없는 페이지보다 많은 페이지에서 vm 활동이 높음) 때문일 것으로 가정했습니다. 또한 vm.swappiness를 1로 설정했습니다. 급격한 변화를 눈치 채지 못했습니다.
Raghu

훌륭한 매뉴얼 에 따르면 , "메모리가 부족한 상태에서는 거대한 페이지를 교체 할 수 없습니다." 나는 이것이 w / r / t 표준 메모리에서 좋은 대답이라고 생각하지만 hugepages에는 그렇지 않습니다.
Dan Pritts

5

핵심

현재 조각화 인덱스를 사용하려면 다음을 사용하십시오.

sudo cat /sys/kernel/debug/extfrag/extfrag_index

커널 메모리 조각 모음을 실행하려면 다음을 수행하십시오.

sysctl vm.compact_memory=1  

또한 THP (Transparent Huge Pages)를 끄거나 스왑을 비활성화 (또는 감소 swappiness) 해보십시오 .

사용자 공간

사용자 공간 조각화를 줄이려면 다른 할당자를 시도해보십시오 jemalloc( 예 : 훌륭한 내부 검사 기능 이있어 할당 자 내부 조각화에 내부를 제공합니다).

프로그램을 다시 컴파일하거나 다음을 사용하여 프로그램을 실행하여 사용자 정의 malloc으로 전환 할 수 있습니다 LD_PRELOAD. LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app ( THP와 메모리 메모리 할당 자 간의 상호 작용에 주의하십시오 )

메모리 조각화와 약간 관련이 없지만 (메모리 압축 / 마이그레이션에 연결됨) 각 NUMA 노드마다 하나씩 여러 서비스 인스턴스를 실행하여을 사용하여 바인딩하려는 경우가 있습니다 numactl.


1
스왑 비활성화가 도움이 될 수 있다고 생각하는 이유는 무엇입니까? 나에게 스왑을 비활성화하면 더 많은 상처를 입을 가능성이 더 높습니다.
kasperd

1
원래 게시물에 충분한 정보가 없기 때문에 프로세스가 누출되어 스왑을 시작했을 수 있습니다. 또한 거의 모든 프로덕션 시스템에서 스왑을 사용해야하는 합당한 이유가 없습니다 (학생을위한 공유 워크 스테이션에만 해당).
SaveTheRbtz

2
스왑 공간이 충분하면 성능이 향상됩니다. 스왑 공간이 충분하지 않으면 성능 문제가 발생하여 스왑을 활성화 할 수 있습니다.
kasperd

1
@SaveTheRbtz 프로덕션 시스템에서 스왑을 사용해야하는 좋은 이유는 시스템에 유용하다고 생각되는 경우에만 사용할 수있는 옵션을 더 많이 제공하기 때문입니다. 또한, 몇 시간 동안 액세스하지 않았고 액세스 할 수없는 수정 된 페이지를 소중한 실제 메모리에서 추출 할 수 있습니다. 마지막으로, 시스템이 사용되는 것보다 훨씬 많은 메모리가 예약 된 경우를 시스템이 제대로 처리 할 수 ​​있습니다.
David Schwartz

2
"유익하다고 생각되는 경우에만"-휴리스틱을 추가하고 시스템을 예측하기 어렵게 만듭니다. 또한 페이지 교체 알고리즘 (스왑 및 익명으로 사용 mmap)은 다른 커널 (예 : Linux vs FreeBSD) 또는 동일한 OS의 다른 버전 (2.6.32 vs 3.2 vs 3.10)에서 다르게 구현됩니다. ..] [...] 실제 메모리에서 꺼내기 "-메모리 누수를 숨길 수 있습니다. "사용 된 것보다 훨씬 많은 메모리가 예약 된 경우 처리"-시스템이 느리면 시스템이 다운되는 것보다 나빠서 "정상"이 의심됩니다.
SaveTheRbtz

4

큰 페이지를 사용하면 Linux에서 추가 메모리 조각화가 발생하지 않아야합니다. 방대한 페이지에 대한 Linux 지원은 공유 메모리 (shmget 또는 mmap를 통해)에 대해서만 사용되며 사용 된 방대한 페이지는 시스템 관리자가 특별히 요청하고 사전 할당해야합니다. 일단 메모리에 있으면 고정되어 스왑되지 않습니다. 메모리 조각화에 직면하여 거대한 페이지를 교체해야하는 문제는 정확히 메모리에 고정되어있는 이유입니다 (2MB의 대용량 페이지를 할당 할 때 커널은 512 개의 연속 된 사용 가능한 4KB 페이지를 찾아야하는데 이는 존재하지 않을 수도 있음).

거대한 페이지의 Linux 설명서 : http://lwn.net/Articles/375098/

메모리 조각화로 인해 큰 페이지 할당 속도가 느려질 수 있지만 (큰 페이지로 인해 메모리 조각화가 발생하는 경우는 아님) 한 가지 상황이 있습니다 . 이는 응용 프로그램에서 요청한 경우 시스템이 큰 페이지 풀을 늘리도록 구성된 경우입니다. / proc / sys / vm / nr_overcommit_hugepages가 / proc / sys / vm / nr_hugepages보다 큰 경우이 문제가 발생할 수 있습니다.


실제로 -TLB 누락을 방지하기 때문에 일반적으로 성능에 도움 이됩니다 (설명은 링크 된 기사 참조).
Dan Pritts

0

/proc/buddyinfo매우 유용하다. 이 Python 스크립트와 같이 멋진 출력 형식으로 더 유용합니다.

https://gist.github.com/labeneator/9574294

거대한 페이지의 경우 2097152 (2MiB) 크기 이상의 무료 조각이 필요합니다. 투명한 거대한 페이지의 경우 커널에 일부를 요청하면 자동으로 압축되지만 얼마나 많은 수를 볼 수 있는지 보려면 루트 실행으로하십시오.

echo 1 | sudo tee /proc/sys/vm/compact_memory

또한 큰 페이지는 조각화에 큰 문제를 일으 킵니다. 거대한 페이지를 얻을 수 없거나 그 존재로 인해 커널이 추가 정보를 얻으려고 많은 시간을 소비합니다.

나에게 맞는 해결책이 있습니다. 몇 대의 서버와 랩톱에서 사용합니다. 가상 머신에 적합합니다.

kernelcore=4GLinux 커널 명령 행에 옵션을 추가하십시오 . 내 서버에서는 8G를 사용합니다. 커널이 해당 메모리 외부에있는 것을 할당하지 못하므로 숫자에주의하십시오. 많은 소켓 버퍼가 필요하거나 수백 개의 드라이브에 디스크 쓰기를 스트리밍하는 서버는 이와 같이 제한되지 않습니다. 슬래브 또는 DMA에 대해 "고정"되어야하는 모든 메모리 할당이이 범주에 있습니다.

다른 메모리는 모두 "이동식"이되어 엄청난 페이지 할당을 위해 멋진 덩어리로 압축 될 수 있습니다. 이제 투명한 거대한 페이지가 예상대로 이륙하고 작동 할 수 있습니다. 커널에 2M 페이지가 더 필요할 때마다 4K 페이지를 다른 곳에 다시 매핑 할 수 있습니다.

그리고 이것이 제로 카피 직접 IO와 어떻게 상호 작용하는지는 확실하지 않습니다. "이동식 영역"의 메모리는 고정되어 있지 않지만 직접 IO 요청은 DMA에 대해 정확히 수행합니다. 복사 할 수 있습니다. 어쨌든 가동 영역에 고정 될 수 있습니다. 두 경우 모두 아마 당신이 원하는 것이 아닐 수도 있습니다.

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