스왑오프가 왜 그렇게 느린가요?

스왑오프가 왜 그렇게 느린가요?

어쩌다가 우연히 14GB RAM을 교체하게 되었습니다. 범인을 죽이고 나면 또 여유 메모리가 많이 생겨서 그럴 수 있을 거라 생각했어요.중요한 데이터 가져오기다시. 그래서 32GB 중 5GB와 14GB의 스왑 공간을 사용하여 실행했는데 swapoff -a...4시간 후에 작업의 절반 정도가 완료되었습니다.

이는 1MB/초 미만을 의미하는 반면, 200MB/초는 쉽게 복사할 수 있습니다. 내 스왑 영역은 암호화되어 있지만 모든 일반 파티션도 마찬가지입니다.에스니상당한 CPU 부하가 발생하지 않습니다(그리고 스왑 공간을 채우는 데 몇 분 밖에 걸리지 않습니다). 최적화해야 할 특별한 이유는 없지만 swapoff어떻게 그렇게 느릴 수 있는지 궁금합니다.


데이터를 더 추가하면 됩니다. 4개의 하드 드라이브 각각에 대해 32GB의 메인 메모리와 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

파티션의 일부를 읽는 것은 전체 파티션을 읽는 것보다 느리지 않습니다. 그러나 약 1/10을 읽으면 시간이 약 100배 더 오래 걸립니다.

나는 swapoff두 프로세스 모두에서 디스크(LED로 "측정")와 마찬가지로 CPU가 대부분 유휴 상태(코어의 10% 정도)인 것을 확인했습니다. 나는 또한 스왑 공간이 차례로 폐쇄되는 것을 보았습니다.

답변1

먼저, 하드 드라이브에서 무엇을 기대할 수 있는지 살펴보겠습니다. 하드 드라이브는 200MB/s에 도달할 수 있습니다.하나씩. 탐색 시간을 고려하면 다음과 같을 수 있습니다.많은더 느리게. 임의의 예로 Seagate의 최신 3TB 디스크 사양을 살펴보세요.ST3000DM001:

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

  • 평균 탐색 읽기: <8.5ms

  • 섹터당 바이트: 4,096

검색할 필요가 없고 스왑이 디스크 가장자리 근처에 있는 경우 최대 속도 =210MB/초

그러나 스왑 데이터가 완전히 분산된 경우 최악의 경우 읽은 모든 섹터를 검색해야 합니다. 이는 8.5밀리초마다 4KB만 읽을 수 있음을 의미합니다. 즉, 4KB / 0.0085 =470KB/초

그러니까 당장은 그렇지 않아믿을 수 없는실제로 하드 드라이브의 속도로 실행되고 있습니다.


즉, 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

이 버그 보고서는 종료되었으며 해결되지 않았습니다.

멜 고먼의 책Linux 가상 메모리 관리자 이해"약간 구식이지만 작업 속도가 느리다는 데 동의합니다.

예상한 대로 영역 비활성화를 담당하는 함수가 호출됩니다 sys_swapoff(). 이 기능은 주로 업데이트와 관련이 있습니다 swap_info_struct. 각 콜아웃 페이지의 페이지 매기기의 주요 작업은 다음과 같습니다 try_to_unuse(). 극도로값비싼.

2007년부터 Linux-kernel 메일링 리스트에서 이 주제에 대해 "더 많은 논의"가 있었습니다.교환 속도 향상"--비록 그들이 토론하는 속도는 당신이 보는 것보다 약간 빠르지만요.


이것은 거의 사용되지 않기 때문에 일반적으로 간과될 수 있는 흥미로운 질문입니다 swapoff. 정말로 추적하고 싶다면 첫 번째 단계는 디스크 사용 패턴을 더 자세히 살펴보는 것입니다(아마도 또는 또는 같은 더 강력한 도구를 사용 atop하여 ). 과도한 검색, 소규모 I/O 작업, 지속적인 재작성, 데이터 이동 등을 살펴봐야 합니다.iostatperfsystemtap

답변2

내 노트북에도 같은 문제가 있습니다. 노트북에는 SSD가 장착되어 있으므로 검색 시간은 문제가 되지 않습니다.

내가 찾은또 다른 설명. 다음은 발췌입니다

현재 작동하는 방식으로 swapoff는 스왑 파티션에서 스왑 아웃된 각 메모리 페이지를 살펴보고 이를 사용하는 모든 프로그램을 찾으려고 시도합니다. 즉시 찾지 못하면 실행 중인 모든 프로그램의 페이지 테이블을 살펴봅니다. 최악의 경우에는 파티션에서 교체된 모든 페이지에 대해 모든 페이지 테이블을 확인합니다. 맞습니다. 동일한 페이지 테이블이 계속해서 확인됩니다.

따라서 이것은 커널 문제이지 다른 문제는 아닙니다.

답변3

예, 이 swapoff메커니즘은 매우 비효율적입니다. 해결책은 간단합니다. 교체된 페이지가 아니라 프로세스를 반복하는 것입니다. 다음 Python 스크립트를 사용하세요(저는 관련이 없습니다).

git clone https://github.com/wiedemannc/deswappify-auto
cd ./deswappify-auto
sudo python3 deswappify_auto.py -d -v info

데몬 작동 모드는 자주 절전 모드에 들어가는 데스크톱/노트북 컴퓨터에만 적합하다는 점에 유의하세요. 나는 그것을 서버 시스템에서 데몬으로 실행하지 않을 것입니다. 잠시 동안 실행하고 일부 프로세스를 처리했다고 보고할 때까지 기다린 다음 중지하고 시도하십시오.

swapoff /dev/x

이제 대부분의 페이지가 스왑 및 메모리에 있으므로 swapoff할 일이 거의 없으며 속도도 꽤 빨라질 것입니다(수백 MB/s로 표시됩니다).

이전 역사적 부분

앞서 언급한 Python 스크립트는 이 답변의 나머지 부분을 기반으로 하며 결과적으로 내 개선 사항입니다.이 오래된 답변작가:지롱. 스크립트가 더 안전하기 때문에 권장합니다최후의 방어선으로 내 답변의 나머지 부분을 시도해 보세요.:

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

주요 한 줄의 코드는 /proc를 많이 읽는다는 점을 제외하면 안전합니다.

수동 검사를 위해 준비된 하위 명령은 다음과 같습니다.안전하지 않음. 각 명령은 스왑에서 메모리 세그먼트를 읽는 동안 프로세스를 일시 중지합니다. 따라서 일시 중단된 프로세스를 허용하지 않는 것은 안전하지 않습니다. 내가 보고 있는 전송 속도는 분당 약 1GB입니다. (앞서 언급한 Python 스크립트는 이 결함을 제거합니다).

또 다른 위험은 시스템에 너무 많은 메모리 압력을 가하는 것입니다.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정렬에 적합하지만 내 목적에는 적합합니다. 숫자 정렬을 어떻게 하는지 모르겠습니다.

답변4

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

"Linux 커널 3판 이해"의 724페이지를 참조하세요.

관련 정보