web-dev-qa-db-ja.com

Linuxの応答性、メモリ、およびページングを制御する方法

オーバーフローに関する最初の質問=)... + 100バウンティ。今まで本当に気になっていたことは考えられませんでした。

Linuxデスクトップの応答性の状態に本当にうんざりしています。 http://brainstorm.ubuntu.com/item/85/ -空きRAMが少ない状況、またはディスクスループットが高い状況では、システムはクロール;これは、まともなパフォーマンスを必要とするアプリケーションにとっては絶対にひどいものです。さらに、UIは完全に応答しません。たとえば、これをOS Xと比較してください。アプリケーションがリソースを占有している場合は、いつでもオプションをクリックして強制終了できますが、Linuxでは、Alt-Tabまたはデスクトップの切り替え、さらにはctrl-alt-f1で取得することもできません。ターミナル-できます。1回の操作で約1〜2分かかります。

私はgkrellmを使用しているので、状況が明らかになるのを見ることができます。通常、メモリ使用率がかなり高くなるか、ディスクスループットが劇的に向上します。

2.6GHzのクアッドコアと4GBの800MHzDDR2を備えた悪いハードウェアではありませんRAM(6GBでしたが、ハードウェアの非互換性のため、古いセットと組み合わせることができませんでした) )RAMを増やす必要がある場合、この問題は解決する可能性がありますが、それが問題の核心であるとは感じていません。異なるディスクに2つのスワップパーティションがあります。

問題は3つあると思います。

  • 大量のメモリを占有する暴走プログラム-これらのプログラムについては、に制限を設けて法律を制定する必要があります。
    • (例:Chromeのタブ。それぞれが20〜50 MBで、一部は数百MBを使用できます)
    • (たとえば、update-dbやインデクサーのような他のプログラムは、実行するたびにシステムのクロールを遅くしていたため、無効にしてcronから削除する必要がありました)
  • ある種のカーネルまたはバスの競合で何かひどいことが起こっているため、ディスクスループットが高い状況では、システム全体がクロールするのが遅くなります(おそらく重要なプログラムをページアウトすることによって)
  • カーネルは、メモリ、ページング、さらにはプロセッサの使用率などのリソースの観点から、UIや重要なプログラムを優先していません

賛成票は次の場所に移動します。

したがって、私はそのようなプログラムがすべてなくなる解決策を探しています。特に、システムや他のプログラムが完全に影響を受けず、十分な時間応答する一方で、プロセスが比例して遅くなるような解決策を探しています。手動で何かを殺します。また、ウィンドウマネージャープロセス(およびUIの応答性に影響を与える可能性のあるその他のもの)は、すべての状況で応答する必要があります。

特に私は/etc/security/limits.confman limits.conf)に興味を持っていますが、これはユーザーごとの制御しかできないのではないかと心配しています。ファイル内のコメント付きの例は、説明やどこから始めればよいか不透明に見えます。 limits.confが機能することを望んでいますが、機能しなかった場合、問題の適切な解決策ではなかった場合、または達成しようとしているほど詳細な場合でも、驚くことはありません。再びlimits.confが機能すると仮定すると、プロセス名ごとのlimits.confが理想的です。私はこの時点ですべての解決策を受け入れていますが、人々が提供するlimits.confを試して、それが機能するかどうかをテストできれば幸いです。

また、OSXがこのような優れたUI応答性を維持する方法についての洞察を得ることも役立つ場合があります。

/tmpフォルダーとキャッシュフォルダーをtmpfsに配置するように調整しましたが、通常、ディスク使用率はほぼゼロです。

漠然と関連するトピック:

  • メモリオーバーコミット

私がうまくいくとは思わない答え:

  • swapoff(これにより、メモリを大量に消費するプログラムは殺人を免れ、メモリが本当に悪い場合はシステムが完全にフリーズします-スワッピングの前にOOM-killerを呼び出し、特定のターゲットをターゲットにするTweakを提案できる人に賛成ですプログラム)
  • echo ?? > /sys/.../swappiness(認識できる効果なし)
  • Nice(機能したことはありません)
  • ionice(違いに気づかなかった)
  • selinux(プログラムの非互換性は悪夢のようです)
  • リアルタイムLinux、つまりカーネルに割り込むことができます(カスタムカーネルのコンパイルと更新を処理したくない。リポジトリに移行した場合は問題ない可能性があります)
  • *
27
user76871

システムが頻繁に交換されているようです。 vmstat 1を使用すると、いくつかの詳細が明らかになる場合があります。ターミナルウィンドウで実行し、スローダウンが開始されたときに切り替えます。

/ tmpと "cache"をtmpfsに入れるのではなく、noatimeオプションでマウントされた通常のディスクファイルシステムを使用します。多くの場合、使用されるデータはとにかくキャッシュに残り、古いデータをディスクに書き込んで、アプリケーション用にRAMを解放できます。/tmpやキャッシュが大きくなると、これは大いに役立つ可能性があります。

6
Turbo J

私はカーネル開発者ではありませんが、何度もこの問題に遭遇したため、この問題について哲学的に何年も費やしました。私は実際に状況全体の比喩を思いついたので、それをお話ししましょう。私の話では、「スワップ」のようなものは存在しないと仮定します。とにかく最近の32GBRAMではスワップはあまり意味がありません。

水がパイプを介して各建物に接続されており、町が容量を管理する必要があるあなたの近所を想像してみてください。毎秒100ユニットの水しか生産していないと仮定しましょう(そして、貯水タンクがないため、未使用の容量はすべて無駄になります)。各家(家=小さなアプリ、端末、時計ウィジェットなど)には、1秒あたり1単位の水が必要です。あなたの人口は90のようで、誰もが十分な水を手に入れるので、これはすべて素晴らしくて良いです。

今、市長(=あなた)はあなたが大きなレストラン(=ブラウザ)を開きたいと決心しました。このレストランには複数の料理人(=ブラウザタブ)が収容されます。各料理人は毎秒1単位の水を必要とします。あなたは10人の料理人から始めるので、近所全体の総水消費量は100単位の水であり、それでもすべて良好です。

今、楽しいことが始まります。あなたは別の料理人をあなたのレストランに雇い、それは明らかにあなたが持っていない総水必要量を101にします。あなたは何かをする必要があります。

水管理(=カーネル)には3つのオプションがあります。

1。最初のオプションは、最近水を使用しなかった家のサービスを切断することです。これは問題ありませんが、切断された家が再び水を使用したい場合は、長い登録プロセスを再度実行する必要があります。管理者は複数の家を切り離して、より多くの水資源を解放することができます。実際、彼らは最近水を使用しなかったすべての家を切断し、それによってある程度の自由水を常に利用できるようにします。

あなたの町は機能し続けていますが、欠点は進歩が止まるということです。あなたの時間のほとんどはあなたのサービスを回復するために水管理を待つことに費やされます。

これは、カーネルがファイルでバックアップされたページで行うことです。大きな実行可能ファイル(chromeなど)を実行すると、そのファイルがメモリにコピーされます。メモリが不足している場合、または最近アクセスされていないパーツがある場合、カーネルはそれらのパーツをディスクからリロードできるため、それらのパーツを削除できます。これが過度に行われると、すべてがディスクIOを待機しているだけなので、デスクトップが停止します。大量のIOを実行し始めると、カーネルは最近使用されていないページも多数ドロップすることに注意してください。これが、DVD画像のようないくつかの大きなファイルをコピーした後、バックグラウンドアプリに切り替えるのに時間がかかる理由です。

私はヒックアップが嫌いで、あなたはそれを制御できないので、これは私にとって最も厄介な行動です。それをオフにできるといいですね。私はの線に沿って何かを考えています

sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c

次に、vm_swappinessを-1に設定して、これを無効にすることができます。これは私の小さなテストでは非常にうまく機能しましたが、残念ながら私はカーネル開発者ではないので、誰にも送信しませんでした(そして明らかに上記の小さな変更は完了していません)。

2。経営陣は、新しい料理人の水要求を拒否する可能性があります。これは最初は良い考えのように聞こえます。ただし、2つの欠点があります。第一に、水を使わないのにたくさんの水サブスクリプションを要求する会社があります。これを行う理由の1つは、追加の水が必要なときに水管理者と話すことによるオーバーヘッドをすべて回避することです。彼らの水の使用量は、一日の時間に応じて上下します。例えば。レストランの場合、会社は深夜に比べて正午にはるかに多くの水を必要とします。したがって、彼らは使用する可能性のあるすべての可能な水を要求しますが、それは深夜の間に水の割り当てを無駄にします。問題は、すべての企業がピーク時の使用量を正しく予測できるわけではないため、はるかに多くの要求を行うことです。これにより水管理のキャパシティプランニングが困難になりますが、その代わりに、企業は水管理と再び連携する必要がなくなるため、内部プロセスを簡素化および高速化できます。

これは、Javaの仮想マシンが行うことです。起動時に大量のメモリを割り当て、そこから動作します。デフォルトでは、カーネルはJavaアプリが実際にメモリの使用を開始したときにのみメモリを割り当てます。ただし、オーバーコミットを無効にすると、カーネルは予約を真剣に受け止めます。割り当てが成功するのは、次の場合のみです。実際にはそのためのリソースがあります。

ただし、このアプローチにはもう1つ、より深刻な問題があります。ある会社が(10段階ではなく)毎日1単位の水を要求し始めたとしましょう。最終的には、空きユニットが0の状態になります。これで、この会社はこれ以上割り当てることができなくなります。とにかく大企業を気にする人は大丈夫です。しかし、問題は、小さな家もそれ以上の水を要求できないということです!観光客の突然の流入に対処するために小さな公衆トイレを建てることはできません。近くの森の火事に非常用水を供給することはできません。

コンピューター用語:オーバーコミットせずにメモリが非常に少ない状況では、新しいxtermを開くことができず、マシンにSSHで接続できず、新しいタブを開いて可能な検索を行うことができません。修正。つまり、オーバーコミットを無効にすると、メモリが不足しているときにデスクトップが役に立たなくなります。

これは、会社が水を使い始めたときに問題を処理する興味深い方法です。水管理はそれを爆破します!文字通り:それはレストランのサイトに行き、そこにダイナマイトを投げ込み、爆発するまで待ちます。これにより、町の水必要量が瞬時に大幅に削減され、新しい人々が入居したり、公衆トイレを作成したりできます。市長として、今回は水が少なくて済むことを期待してレストランを再建できます。たとえば、すでに人が多すぎる場合は、レストランに入らないように指示します(たとえば、開くブラウザのタブが少なくなります)。

これは実際には、カーネルがすべてのオプションを使い果たしてメモリが必要になったときに実行することです。つまり、OOMキラーを呼び出します。 (多くのヒューリスティックに基づいて)大きなアプリケーションを選択して強制終了し、大量のメモリを解放しますが、応答性の高いデスクトップを維持します。実際、Androidカーネルはこれをさらに積極的に実行します。メモリが少ないときに最も使用頻度の低いアプリを強制終了します(最後の手段としてのみ実行するストックカーネルと比較して)。これはと呼ばれます。 Androidのバイキングキラー。

これは問題の最も簡単な解決策の1つだと思います。これよりも多くの選択肢があるわけではないので、早めに解決してみませんか?問題は、カーネルがOOMキラーの呼び出しを回避するために非常に多くの作業を行うことがあることです。そのため、デスクトップが非常に遅く、カーネルがそれについて何もしていないことがわかります。しかし、幸いなことに、OOMキラーを自分で呼び出すオプションがあります!まず、マジックsysrqキーが有効になっていることを確認します(例:echo 1 | Sudo tee /proc/sys/kernel/sysrq)カーネルのメモリが不足していると感じたら、Alt + SysRQ、Alt + fを押すだけです。

OK、それでいいのですが、試してみたいですか?メモリ不足の状況は非常に簡単に再現できます。私はそのための非常にシンプルなアプリを持っています。 2回実行する必要があります。最初の実行で空き容量が決まりますRAM、2回目の実行でメモリ不足の状況が発生します。この方法では、スワップが無効になっていることを前提としています(たとえば、Sudo swapoff -a)。コードと使用法は次のとおりです。

// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int limit = 123456789;
    if (argc >= 2) {
        limit = atoi(argv[1]);
    }
    setbuf(stdout, NULL);
    for (int i = 1; i <= limit; i++) {
        memset(malloc(1 << 20), 1, 1 << 20);
        printf("\rAllocated %5d MiB.", i);
    }
    sleep(10000);
    return 0;
}

そして、これがあなたがそれをどのように使うかです:

$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed

最初の呼び出しで、31,118MiBの空きRAMがあることが検出されました。そこで、アプリケーションに31,110 MiB RAMを割り当てるように指示しました。これにより、カーネルはそれを強制終了せず、ほとんどすべてのメモリを消費します。システムがフリーズしました。マウスポインタも動かなくなりました。押しました。 Alt + SysRQ、Alt + fを実行すると、eatmemプロセスが強制終了され、システムが復元されました。

メモリが少ない状況で何をするかについてオプションを説明しましたが、(他の危険な状況と同じように)最善のアプローチは、そもそもそれを回避することです。これを行うには多くの方法があります。私が見た一般的な方法の1つは、動作に問題のあるアプリケーション(ブラウザーなど)をシステムの他の部分とは異なるコンテナーに入れることです。その場合、ブラウザはデスクトップに影響を与えることができません。しかし、予防自体は質問の範囲外なので、私はそれについては書きません。

TL; DR:現在、ページングを完全に回避する方法はありませんが、オーバーコミットを無効にすることでシステム全体の停止を軽減できます。ただし、メモリが少ない状況でもシステムは使用できませんが、方法は異なります。上記に関係なく、メモリが少ない状況では、Alt + SysRQ、Alt + fを押して、カーネルが選択した大規模なプロセスを強制終了します。システムは、数秒後に応答性を回復するはずです。これは、マジックsysrqキーが有効になっていることを前提としています(デフォルトでは有効になっていません)。

5
ypsu

すべての一時ファイルとキャッシュファイルをtmpfsに置くと、空き容量が減少しますRAM)ので、システムが必要以上に早くスワップする可能性がありますこれなしに。

過負荷になっているある種のカーネル機能またはドライバーに依存しているアプリケーションがあるようです。ブラウザとインデクサーを使用している以外のアプリケーションの種類や、インデクサーを無効にしていることについては、あまり詳しく説明しません。

LXDEやIceWMなど、リソースの消費量が少ないデスクトップ環境またはウィンドウマネージャーに切り替えてみてください。仕事では、LXDEがインストールされたLinuxシステムと、最小限のデスクトップ環境用のROX-Filerを使用しています。このLinuxシステムの目的は、VMWare Playerを実行して、Windows XPとWindows7を同時に実行できるようにすることです。ハードウェアの仕様はあなたの言うことと似ており、応答性の問題はあまりありません。この重い負荷の下で、私はハードウェアを通過させています。Linux自体にany応答性の問題はありません(通常、VMが1秒待たされ、2つのVM間で1つのディスクを共有します) + 1 OSこれは予想されます)そして私が望むときはいつでもVMを一時停止またはシャットダウンすることができました。これにはLinux上でFirefoxをバックグラウンドで実行することが含まれます。

だから私には、あなたが実行している特定のアプリケーションに関するいくつかの問題を指摘しています。

DMAはディスクドライブで有効になっていますか?(hdparmを使用)フルディスク暗号化を使用している場合、すべてのディスクトラフィックがCPUを通過する必要があり、その多くが無効になります。 DMAの利点。その影響は、ディスクトラフィックが多いと、CPUが急上昇し、システム全体の速度が低下することです(編集:明確にするために、DMA無効OR dm-cryptを使用すると、ディスクトラフィックが多いときにCPUが高くなります)

4
LawrenceC

これは、Linuxのスケジューラでよくある問題です。 IO重いアクティビティが発生するたびに、システムの速度が低下します。カーネルのハッキングに興味がない限り、状況を改善するためにできることはあまりありません:)

多分これらは助けることができます:

http://www.phoronix.com/scan.php?page=article&item=linux_2637_video&num=1

http://www.osnews.com/story/24223/Alternative_to_the_200_Lines_Kernel_Patch_that_Does_Wonders_

1
Lamnk

質問は2年以上前のものであり、@ ypsuの答えは素晴らしいですが、RAMがないために、Linuxベースのシステムが悪くなっている状況はまだここにあります。

この問題に関する私の観察結果は次のとおりです。スワップがまったくない場合でも、システムのメモリが不足すると、100%のディスク負荷であるためハードドライブインジケータが点灯します。この事実を考えると、根本的な原因は、カーネルがディスクから復元できるもの、つまり共有ライブラリをアンロードすることによってメモリを解放しようとすることであると思われます。 GUIアプリケーションには通常大量の共有ライブラリがあるため、システムはそれらの一部をアンロードするだけで十分であると考えるかもしれませんが、それはアンロードされたライブラリを戻す必要がある次のユーザースペース操作までしか機能しません。これは、共有ライブラリをアンロードして再度ロードするという無限のループを引き起こす可能性が最も高いシナリオのようです。

手遅れになる前に最もメモリを消費するプロセスを強制終了するユーザースペースデーモンとして機能するプロジェクトがあります: https://github.com/rfjakob/earlyoom

また、メモリを大量に消費するアプリケーション(Chromeなど)には、適切なメモリ制限を備えたDockerコンテナを使用していました。

0
Vlad Frolov