스왑 오프가 어떻게 느려질 수 있습니까?


77

어떻게 든 14GB의 메모리를 교체했습니다. 범인을 죽인 후, 나는 다시 많은 양의 여유 메모리를 가지고있어서 중요한 데이터를 다시 가져올 수 있다고 생각 했다. 따라서 32GB 중 5GB를 사용하고 14GB의 스왑 공간을 사용하여 swapoff -a.....를 실행 했으며 약 4 시간 후에 작업의 절반이 완료되었습니다.

이것은 1MB / s 미만을 의미하지만 200MB / s를 쉽게 복사 할 수 있습니다. 내 스왑은 암호화되었지만 모든 일반 파티션과 마찬가지로 aes-ni를 사용 하면 눈에 띄는 CPU로드가 발생하지 않습니다 (스왑 공간을 채우는 데 몇 분 밖에 걸리지 않았습니다). 최적화해야 할 특별한 이유는 swapoff없지만 어떻게 느려질 수 있을지 궁금합니다.


더 많은 데이터 추가하기 : 메인 메모리는 32GB이고 4 개의 하드 디스크 각각에 32GB의 스왑 공간이 있습니다. 전체 스왑 공간은 5 분 이내에 해독 (읽고 해독 가능) 할 수 있습니다.

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

파티션의 일부를 읽는 것이 모든 것을 읽는 것보다 느릴 수는 없습니다. 그러나 약 10 분의 1을 읽는 데는 약 100 배가 걸립니다.

나는 swapoff두 CPU 동안 대부분 유휴 상태 (아마도 한 코어의 10 %)와 디스크 (LED에 의해 "측정")가 유휴 상태 인 것을 관찰했다 . 또한 스왑 공간이 차례로 꺼지는 것을 보았습니다.


1
시스템이 스왑 된 페이지를 RAM으로 다시로드 할 때도 동일한 현상이 발생합니까? 예를 들어, 시스템이 디스크에 일시 중단되어 시작된 경우 모든 것이 스왑 아웃되고 RAM으로 다시로드됩니다. 나에게도 너무 느린 것 같습니다.
Petr Pudlák

모든 스왑 장치가 동일한 우선 순위로 활성화되어 있습니까?
Nils

@Petr Pudlák : 디스크 일시 중단은 약간 다릅니다. RAM 내용을 스왑 영역의 여유 공간에 기록하기 만하면이 작업이 훨씬 더 빠릅니다. 암호화 된 스왑에서는 작동하지 않으므로 시도 할 수 없습니다.
maaartinus

@Nils : 예. 우선 순위는 동일하며 디스크와 파티션도 동일합니다.
maaartinus

그것은 더 이상하게 만듭니다. 이 경우 스왑은 모든 디스크에 걸쳐 스트라이핑됩니다. 매우 빠릅니다. iostat -d 5동안 디스크에 낮은 IO 가 표시 되었습니까 swapoff?
Nils

답변:


53

먼저, 하드 드라이브에서 기대할 수있는 것을 살펴 보겠습니다. 하드 드라이브는 200MB / s를 순차적으로 수행 할 수 있습니다 . 탐색 시간을 고려하면 훨씬 느려질 수 있습니다 . 임의의 예를 선택하려면 Seagate의 최신 3TB 디스크 중 하나 인 ST3000DM001 의 사양을 살펴 보십시오 .

  • 최대 지속 데이터 속도 : 210MB / s

  • 평균 판독 값 찾기 : <8.5ms

  • 섹터 당 바이트 : 4,096

검색 할 필요가없고 스왑이 디스크 가장자리에 가까운 경우 최대 속도 = 210MB / s 까지 예상 할 수 있습니다.

그러나 스왑 데이터가 완전히 조각난 경우 최악의 시나리오에서는 읽은 모든 섹터를 찾아야합니다. 즉, 8.5ms마다 4KB 또는 4KB / 0.0085 = 470KB / s 만 읽을 수 있습니다.

따라서 배트 바로 에서 실제로 하드 드라이브 속도에 맞서는 것은 상상할 수 없습니다 .


즉, swapoff너무 느리게 실행되고 페이지가 빠르게 작성된 경우 (순서대로) 페이지를 순서대로 읽어야 하는 것은 어리석은 것처럼 보입니다 . 그러나 그것은 커널이 작동하는 방식 일 수 있습니다. 우분투 버그 보고서 # 486666 은 같은 문제를 논의합니다 :

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

답글 중 하나는 다음과 같습니다.

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

버그 보고서가 해결되지 않았습니다.

Mel Gorman의 저서 " Linux Virtual Memory Manager 이해 "는 약간 오래되었지만 이것이 느리게 작동한다는 데 동의합니다.

영역 비활성화를 담당하는 기능을 충분히 예측할 수 sys_swapoff()있습니다. 이 기능은 주로 swap_info_struct. 각 페이지 아웃 페이지에서 페이징하는 주요 작업은 책임 try_to_unuse()매우 높습니다.

linux-kernel 메일 링리스트에서 2007 년부터 " 스왑 오프 속도 향상 "이라는 주제에 대해 조금 더 논의하고 있습니다. 비록 그들이 논의하고있는 속도가보고있는 것보다 약간 높습니다


swapoff거의 사용되지 않기 때문에 아마도 일반적으로 무시되는 흥미로운 질문입니다 . 나는 당신이 정말로 그것을를 추적하고자한다면, 첫 번째 단계는 더 신중 디스크 사용 패턴을 시청하려고 할 것이라고 생각한다 (아마와 함께 atop, iostat또는 더욱 강력한 도구와 같은 perf또는 systemtap). 찾아야 할 것은 과도한 탐색, 작은 I / O 작업, 지속적인 재 작성 및 데이터 이동 등일 수 있습니다.


5
훌륭한 설명. 스왑 된 메모리의 큰 부분을 코어 덤프함으로써 unfrag.com
Brandon DuPree

단지 조각화 / 검색 시간이 아닙니다. 내 스왑은 SSD에 있고 임의 읽기는 매우 빠르지 만 스왑 오프 명령은 예상보다 속도가 느리고 SSD로드는 1 % 정도입니다. 커널 또는 스왑 오프 (~ 90-100 % CPU 사용) 어딘가에 목록 걷기가 있다고 생각합니다. 물론 모든 작업이 순차적으로 수행되고 디스크 탐색이 너무 느리면 상당한 시간이 소요될 수 있습니다.
Thomas Guyot-Sionnest

33

SSD가있는 랩톱에서 동일한 문제가 발생했기 때문에 탐색 시간은 문제가되지 않습니다.

나는 다른 설명을 찾았다 . 여기 발췌가 있습니다

현재 작동 방식에 따라 swapoff는 스왑 파티션에서 스왑 아웃 된 각 메모리 페이지를보고이를 사용하는 모든 프로그램을 찾습니다. 만약 그것들을 바로 찾을 수 없다면, 그것들을 찾기 위해 실행중인 모든 프로그램의 페이지 테이블을 볼 것입니다. 최악의 경우 파티션에서 스왑 아웃 된 모든 페이지에 대해 모든 페이지 테이블을 검사합니다. 맞습니다. 동일한 페이지 테이블을 계속해서 확인합니다.

따라서 다른 것보다는 커널 문제입니다.


아닙니다. 커널 문제는 아닙니다. IMHO. swapoff구현 방법 입니다. 스왑 아웃 프로세스 종료시 시간이 오래 걸리지 않습니다.
Marki555

15
커널에있는 스왑 오프 구현에 문제가 있습니다. 따라서 커널 문제입니다! strace swapoff거의 모든 것이 swapoff시스템 호출 을 하는 것임을 알 수 있습니다 .
Nick Craig-Wood

1
48GB RAM (32cores)의 서버가 있으며 6GB의 무료 버그 스왑이 0.7GB로 사용되었습니다. swappiness = 10, 0으로 만들려고 시도한 후 스왑 오프를 시도하여 어떤 일이 발생하는지 확인했습니다. 스왑 오프는 아마도 30 분 정도 걸리며 스왑은 매우 느려집니다. 나는 거의로드가없는 SSD를 가지고 있으며 CPU는 비슷합니다. 스왑 오프 프로세스는 1 CPU 100 %가 필요합니다.
sorin

1
스왑 오프가 어떻게 구현되는지 문제입니다 (커널에서). 몇 년 전 kernel-dev에서 훨씬 더 나은 접근 방식에 대한 토론이 있었지만, 그것이 모호한 사례이며 그것을 바꾸려는 노력을 원하지 않는다고 말합니다.
Marki555

7
1TB RAM (예, TB) 및 2GB 스왑 (Silly SAP 요구 사항)이있는 서버에서는 2GB의 5 %를 해제하는 데 12 시간이 걸렸습니다 (100 %의 CPU 코어 1 개 사용).
Marki555

22

그래, 그 swapoff메커니즘은 엄청나게 비효율적입니다. 해결 방법은 쉽습니다. 프로세스를 반복하는 대신 스왑 된 페이지를 반복하는 것입니다. 이 파이썬 스크립트를 사용하십시오 (나는 제휴하지 않습니다).

git clone https://github.com/wiedemannc/deswappify-auto

데몬 작동 모드는 최대 절전 모드 인 데스크톱 / 노트북에만 해당됩니다. 서버 시스템에서 데몬으로 실행하지 않습니다. 포 그라운드에서 실행하고 일부 프로세스를 처리했다고보고 될 때까지 기다렸다가 중지하고 시도하십시오.

swapoff /dev/x

대부분의 페이지가 이제 스왑과 메모리에 모두 존재하기 때문에 swapoff할 일이 거의 없으며 매우 빠릅니다 (수백 MB / s 보았습니다).

연혁

전술 파이썬 스크립트를 차례로 내 개선했다이 답변의 나머지를 기반으로 이 오래된 대답 에 의해 작성된 jlong를 . 스크립트가 훨씬 안전 하므로 마지막 방어선으로 나머지 답변을 시도하는 것이 좋습니다 .

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

이것은 어쩌면 2 초 실행하고 실제로는 아무것도하지 않습니다, 단지 상위 10 메모리 세그먼트를 (실제로는 더 한 라이너를 인쇄 목록, 그래, 난 않는 복사하고 붙여 넣습니다, 단지 명령을 검토 될 위험을 감수 할 수있는 하나 - 라이너 사랑 쉘; 이들은 실제로 스왑에서 읽습니다).

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

메인 one-liner는 많은 / proc를 읽는 것을 제외하고는 안전합니다.

수동 검사를 위해 준비된 하위 명령은 안전하지 않습니다 . 각 명령은 스왑에서 메모리 세그먼트를 읽는 동안 하나의 프로세스를 정지시킵니다. 따라서 일시 중지를 허용하지 않는 프로세스에서는 안전하지 않습니다. 내가 본 전송 속도는 분당 1 기가 바이트 정도였습니다. (위의 파이썬 스크립트는 그 결함을 제거했습니다).

또 다른 위험은 시스템에 너무 많은 메모리 압력을 가하는 것이므로 일반적인 사항을 확인하십시오. free -m

무엇을합니까?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

이 perl 스크립트의 출력은 스왑 된 페이지를 메모리로 호출 하는 일련의 gdb명령 dump memory (range)입니다.

출력은 크기로 시작하므로 | sort -Vr | head크기 (SSIZE)로 상위 10 개의 가장 큰 세그먼트를 얻기 위해 통과 할 수 있습니다. -V버전 번호-적절한 정렬을위한 스탠드,하지만 내 목적을 위해 사용할 수 있습니다. 숫자 정렬 작업을 수행하는 방법을 알 수 없었습니다.


여기에 숫자 정렬을 사용할 것입니다sort -t = -k 2n
Stéphane Chazelas

9
프로세스 메모리를 들여다보기 위해 gdb를 사용할 필요가없는 것 같습니다 (최소한 최근 커널에서). 하나만 열고 /proc/$pid/mem직접 찾아서 읽을 수 있습니다. 다음은 스 니펫을 기반으로 한 PoC입니다. gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae 이 방법으로 프로세스가 중지되지 않습니다. AFAIK 이로 인한 위험이 없어야합니다.
WGH

10

스왑 오프 중에 사용중인 스왑 슬롯이 감지되면 커널은 먼저 페이지에서 스왑합니다. 그런 다음 unuse_process () 함수는 방금 스왑 된 페이지에 해당하는 모든 페이지 테이블 항목을 찾으려고 시도하여 페이지 테이블을 업데이트합니다. 검색은 철저하고 시간 소모적입니다. 전체 시스템의 모든 메모리 설명자를 방문하여 페이지 테이블 항목을 하나씩 검사합니다.

"Linux Kernel 3rd 버전 이해"의 724 페이지를 참조하십시오.

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