スワップオフはどのように遅くすることができますか?


77

どういうわけか、たまたま14 GBのメモリをスワップアウトしました。犯人を殺した後、私は再びたくさんの空きメモリを持っているので、私は再び重要なデータを持ち込めると思った。したがって、32 GBのうち5 GBを使用し、14 GBのスワップ領域を使用して、私は走りましたswapoff -a...そして4時間後、作業の約半分が終了しました。

つまり、1 MB /秒未満ですが、200 MB /秒で簡単にコピーできます。私のスワップは暗号化されていますが、すべての通常のパーティションも暗号化されており、aes-niを使用すると目立ったCPU負荷が発生しません(そしてスワップスペースを満たすのに数分しかかかりませんでした)。最適化する特別な理由swapoffはないようですが、どうしてそんなに遅くなるのでしょうか?


さらにデータを追加するだけです。メインメモリは32 GBで、4台のハードディスクのそれぞれに32 GBのスワップスペースがあります(確かに過剰ですが、誰が気にしますか?)。スワップスペース全体を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、両方のCPU(一つのコアの多分10%)主にアイドルであったので、ディスクが(LEDによって「測定」)でした。また、スワップスペースが次々にオフになることもわかりました。


1
システムがスワップされたページをRAMにロードするときに同じ現象が発生するのでしょうか?たとえば、システムがディスクにサスペンドされてから起動した場合、すべてがスワップアウトされ、RAMにロードされます。私にとっても非常に遅いようです。
ペトルプドラク

すべてのスワップデバイスが同じ優先度でアクティブ化されていますか?
ニルス

@PetrPudlák:ディスクへのサスペンドは少し異なります。スワップ領域の空きスペースにRAMコンテンツを書き込むだけで、これ(およびサスペンド解除)はおそらくはるかに高速です。暗号化されたスワップでは機能しないため、試すことはできません。
-maaartinus

@Nils:はい、優先順位は同じで、ディスクとパーティションも同じです。
-maaartinus

それはより奇妙になります。この場合、スワップはすべてのディスクにストライピングされます-これは非常に高速です。のiostat -d 5間に、ディスクのIOが低くなりましたswapoffか?
ニルス

回答:


53

最初に、ハードドライブに何が期待できるかを見てみましょう。ハードドライブは200 MB / sを連続して実行できます。シーク時間を考慮に入れると、はるかに遅くなる可能性があります。任意の例を選択するには、Seagateの最新の3TBディスクの1つであるST3000DM001の仕様を見てください

  • 最大持続データレート:210 MB / s

  • 平均読み取りのシーク:<8.5 ms

  • セクターあたりのバイト数:4,096

シークする必要がなく、スワップがディスクの端近くにある場合、最大レート= 210 MB / sを期待できます。

しかし、最悪の場合、スワップデータが完全に断片化されている場合、読み取るすべてのセクターを探す必要があります。つまり、8.5 msごとに4 KB、つまり4 KB / 0.0085 = 470 KB / sしか読み取れないことを意味します。

そのため、すぐに、実際にハードドライブの速度に逆らって走ることは考えられません。


そうは言っても、swapoff実行速度が非常に遅く、ページを順番どおりに読み取らなければならないのは愚かなことです。しかし、それはカーネルの仕組みにすぎないかもしれません。Ubuntuバグレポート#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

返信の1つは次のとおりです。

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()非常に高いことです。

2007年のlinux-kernelメーリングリストには、「speedoff up swapoff」というテーマでもう少し議論があります。


これswapoffはめったに使用されないので、おそらく一般的に無視される興味深い質問です。私はあなたが本当にそれを追跡したい場合は、最初のステップは、より慎重にディスクの使用パターンを監視しようとしていることだと思う(多分にatopiostatまたはさらに強力なツールのようなperfsystemtap)。探すべきものは、過剰なシーク、小さなI / O操作、絶え間ない書き換えとデータの移動などです。


5
素晴らしい説明。断片化のほとんどを回避することは可能だと指摘し、コア・ダンプすることで迅速スワップメモリの大規模なセクションスワップの大半を解放する必要があります。unix.stackexchange.com/questions/254202/...
ブランドン・デュプリー

断片化/シーク時間だけではありません。私のスワップはSSD上にあり、ランダム読み取りは非常に高速ですが、swapoffコマンドは本来よりもかなり遅く、SSDの負荷は約1%utilのままです。カーネルまたはスワップオフ(〜90-100%のCPUを使用)のどこかにリストウォークが関与しているのではないかと考えています。もちろん、すべての作業がシーケンシャルに行われ、ディスクシークも遅い場合、大幅に増加する可能性があります。
トーマス・グヨ=シオンネスト

33

SSDを搭載したラップトップでも同じ問題が発生しているため、シーク時間は問題になりません。

は別の説明を見つけまし。抜粋です

現在の動作では、swapoffはスワップパーティション内のスワップアウトされた各メモリページを調べ、それを使用するすべてのプログラムを見つけようとします。すぐに見つからない場合は、実行中のすべてのプログラムのページテーブルを調べてそれらを見つけます。最悪の場合、パーティション内のスワップアウトされたページごとにすべてのページテーブルをチェックします。そうです-同じページテーブルが何度もチェックされます。

したがって、それは他の何よりもむしろカーネルの問題です。


いいえ、それは私見のカーネルの問題ではありません。swapoff実装方法です。スワップアウトされたプロセスが終了すると、それほど時間がかかりません。
Marki555

15
これは、カーネルにあるswapoffの実装に問題があるため、カーネルの問題です!システムコールを呼び出すだけstrace swapoffで十分かどうかを確認できますswapoff
ニッククレイグウッド

1
48 GB RAM(32コア)のサーバーがあり、6 GBの無料のバグスワップが0.7 GB使用されていました。swappiness = 10、それを0にしようとし、また何が起こるかを見るためにswapoffを試みました。スワップオフには時間がかかり、おそらく30分かかり、スワップを非常に遅く解放します。私はほとんど無負荷でSSDを使用しており、CPUも同様です。1CPUを100%使用するswapoffプロセスを期待しています。
ソリン

1
swapoffの実装方法の問題です(カーネル内)。数年前にkernel-devでより良いアプローチについての議論がありましたが、彼らはそれがコーナーケースであり、それを変更する努力を望まないと言います。
Marki555

7
1 TBのRAM(はい、TB)と2 GBのスワップ(SillyのSAP要件)を備えたサーバーでは、swapoffは12時間で2 GBの5%を解放しました(100%で1 CPUコア)。
Marki555

22

うん、swapoffメカニズムは恐ろしく非効率的です。回避策は簡単です。スワップされたページを繰り返し処理する代わりに、プロセスを繰り返し処理します。このPythonスクリプトを使用してください(私は提携していません):

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

デーモンモードの操作は、多くの場合冬眠されるデスクトップ/ラップトップ専用です。サーバーシステムでデーモンとして実行するのではなく、フォアグラウンドで実行し、プロセスの処理が完了したことを報告するまで待ってから停止してみます。

swapoff /dev/x

現在、ほとんどのページがスワップとメモリの両方に存在swapoffするため、実行することはほとんどなく、非常に高速になります(数百MB / sを見ました)。

先の歴史セクション

前述のpythonスクリプトは、この回答の残りの部分に基づいています。これは、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個のメモリセグメントをリストするだけです(実際には、1ライナーをより多く印刷します。はい、1ライナー大好きです。シェル。これらは実際にスワップから読み取られます)。

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

メインのワンライナーは、多くの/ procを読み取ることを除いて安全です(私にとって)。

手動検査用に準備されたサブコマンドは安全ではありません。各コマンドは、スワップからメモリセグメントを読み取る間、1つのプロセスをハングさせます。したがって、一時停止を許容しないプロセスでは安全ではありません。私が見た転送速度は、毎分1ギガバイトのオーダーでした。(前述のpythonスクリプトはその欠陥を取り除きました)。

もう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
ステファンChazelas

9
(少なくとも最近のカーネルでは)プロセスメモリを覗くためにgdbを使用する必要はないようです。/proc/$pid/mem直接開く、検索する、読むことができます。主にスニペットに基づいたPoCは次のとおりです。
WGH

10

スワップオフ中に、使用中のスワップスロットが検出されると、カーネルは最初にページ内でスワップします。次に、関数unuse_process()は、スワップインされたばかりのページに対応するすべてのページテーブルエントリを見つけようとし、ページテーブルに必要な更新を行います。検索は徹底的で非常に時間がかかります。(システム全体の)すべてのメモリ記述子を訪問し、ページテーブルエントリを1つずつ調べます。

「Linuxカーネル3rdバージョンについて」の724ページを参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.