memoranda2016-10-29Linuxにおける各種メモリについてLinuxで扱う様々な種類や単位のメモリについてまとめておく。メモリというリソースに関する制御や管理について考察する。mlockシステムコールを使うことにより、メモリの内容がディスク上にスワップされないようにする(=Lockする)ことができる。静的(スタック領域)や動的(ヒープ領域)に確保するメモリの最大容量。スワップされたプロセスが使用するディスク上の仮想メモリ空間の最大容量。静的(スタック領域)に確保するメモリの最大容量。ulimitの機能シェル組み込みの機能で、ユーザ毎にCPUやメモリ、ファイル、PIPEなどのリソースの使用量に制限を設ける。ソフトリミットはハードリミットを超えない範囲で設定が可能で、ハードリミットを上げることができるのはrootのみ。ulimitの制御は、setrlimit/getrlimitシステムコールを使って行われる。0なお、ディスク(パーティション)の使用量制限に関してはulimitではなくquotaで行う。quotaユーザ単位・グループ単位でディスク(パーティション)の使用量に制限を設ける。mountオプションとしてusrquota・grpquotaを指定する必要がある。ソフトリミットは猶予期間内であれば超えることができるが、猶予期間を超えるとソフトリミットがハードリミットとなる。ハードリミットは超えることができない。aquota.groupファイル上で行われる。プロセスの仮想メモリ全体のサイズ。実際には使用していない領域を含んでいる。プロセスが仮想メモリの中で、実際に使用しているメモリのサイズ。共有ライブラリのメモリを含むため、各プロセスで重複してカウントされている。スワップアウトされているメモリは含まれない。プロセスが実際に使用しているメモリのサイズ。共有ライブラリのメモリを含むが、そのライブラリを使用しているプロセス数で割っているため、RSSの問題点は解決している。(例)dhclientとcupsdはlibcryptoを共有ライブラリとして利用しており、それぞれのプロセスのRSSとしてカウントされている。rsz)....pmapのRSSとSizeは、実際にメモリに読み込まれているかどうかの違いがある。この違いは、デマンドページングによりページフォルトが発生するまで実際のメモリへの読み込みを遅延する、ことによって現れる。それによって、例えば共有ライブラリの中の実際に使用する関数のみをメモリに読み込んで実行することができる。Sizeは実際には読み込まれておらず、論理アドレスに割り当てただけの部分もカウントしている。デマンドページングはmalloc発行時にも効果を発揮する。mallocを発行すると論理アドレス上ではメモリを割り当てたことになるが、物理メモリ上ではまだメモリ領域は確保されず、実際にメモリに書き込んだ際、初めて物理メモリ上でメモリ領域が確保される。この機構により実際の物理メモリ容量よりも大きいメモリをmallocにより割り当てることができ、これをオーバーコミットと呼ぶ。Killerにより停止されるだろう。オーバーコミットの容量はsysctlである程度制御が可能である。プロセスが確保したメモリ。ディスクに退避(スワップ)されることがある。OSがディスクキャッシュとして確保したメモリ。(Dirtyなもの以外は)もともとディスク上に存在するデータ。tmpfsとして使用されているメモリ。tmpfsはメモリ上にのみ存在するが、スワップの対象となりディスクに書き出される。LRU的に、最近使用されたメモリか、利用されていないメモリか。ディスクに書き込まれていないFile-backedなバッファ。syncでディスクに書き込むと0になり、Cleanなバッファとなる。/proc/sys/vm/drop_cachesで解放される。/proc/sys/vm/drop_cachesで解放される。解放不可能なSlab。直後でもSReclaimableは0にならないが、slabtopで確認するとdentryやinodeがSlabを使用しているのが分かる。バックグラウンドプロセスやカーネルの処理が動いているため、すぐにSlabの割り当てが行われているのだろう。カーネルが使用しているSlab以外のメモリ。デバイス上の物理メモリを含んでいる。デバイス上の物理メモリは/proc/vmallocinfoのioremapの部分。各プロセスにおける論理アドレスから物理アドレスへの変換表。現在CPUで実行中のプロセスのページテーブルは、CR3レジスタでそのメモリアドレスが示される。free/proc/meminfoの内容を元に、メモリの使用量や残量を示してくれる。x86(32bit)では、lオプションはカーネルが使用するLowメモリと、プロセスが使用するHighメモリを分けて表示してくれる。カーネルが使用するLowメモリは、物理アドレスの1MB〜893MBまで、また各プロセスの論理アドレスの3GB〜4GBの領域を占める。x86_64(64bit)では、LowメモリやHighメモリといった区別が無いため、lオプションで表示する場合は全てLowメモリとして表示し、Highメモリは常に0として表示されるようである。必要になったらそこから再利用することでパーフォーマンスが上がる。Slabはオブジェクトキャッシュとも呼ばれる。小さい単位のメモリ割り当て・解放を、その都度メモリから自由に行うとフラグメントの問題を引き起こしやすくなるが、Slabとして保持しておいて再利用することで、少なくともスラブを利用している限りにおいてはフラグメントの問題は起こらない。Slabから実際に使うオブジェクトへメモリを払い出すkmem_cache_freeSlabは単一のオブジェクトを連続したメモリ上に複数格納する。Slabがemptyになると、リープ(OSに戻す)対象となる。Slabのオブジェクトはページに沿って配置されているため、CPUの特定のキャシュラインに集中してしまう。別のオブジェクトがCPUの別のキャッシュラインに載るように、Slabごとに少しフラグメントを持たせてアドレスをずらす。Slabが大量消費されていることでメモリを圧迫する問題(問題?)dentryやinodeはSlabのヘビーユーザであり、それによってSlabが大量に消費されていることがある。3を書き込むことで、Slab(SReclaimable)は解放されるが、Slabを完全に解放してしまうとLinuxとしての性能は格段に落ちる。Linuxには、システムコールから各種ファイルシステムを抽象化して統一的に扱うために、VFSの層が存在する。VFSでは、dentryという構造体を使用してディレクトリ構造やファイル名とinodeとの対応などをキャッシュする。dentryはメモリ上にのみ存在し、ファイルシステムの一部のデータとして存在しているわけではない。ファイルシステムでファイルを管理するためのメタ情報。ファイルのサイズやパーミッション、データブロックの位置などが管理されている。ファイルのデータブロックのキャッシュ。そもそもメモリをたくさん消費しているのはリソースを効率良く使用できている状態とも言えるので、問題なのはそれによってスワッピングが発生しているか否かであり、それはvmstatコマンドのsi,soの項目を確認することで分かる。SlabもLRUによって管理されているはずなので、基本的にはそれにまかせるのが得策なのではないだろうか。vmstatで最初に表示される結果は起動時からの平均値であり、単位時間の結果を確認する場合には二つ目以降を確認する。100を基準として、Slabの比率を増やしたり減らしたりできるらしい。https://www.kernel.org/doc/Documentation/sysctl/vm.txtSlabの肥大化で実際にスワップが発生した問題とその解決方法いきなり上記で書いた内容と矛盾するが、Slabの肥大化によってスワップが発生してしまった事例がある。メモリ圧迫時にはLRUに基づくSlabの解放を期待したがうまく動いてくれなかった、ということになる。cacheを解放するスピードが間に合わないのか、とある。cacheを生成しないのだろうか。この事例から「一時ファイルはtmpfsにおいて処理する」は鉄則だろう。cacheとしてキャッシュする。entryがあればその必要が無いのでディスクI/Oを減らす効果が期待できる。-vコマンドの結果のdentunusdが示す値に含まれているらしい。cacheはDNSでも不要なクエリを発生させないために使われることがある。posix_fadviseとPOSIX_FADV_DONTNEEDをディレクトリ単位で適用することにより、必要なページキャッシュは残しつつ、不要なページキャッシュだけをディレクトリ単位で解放する。tech.mercari.comページキャッシュが不要ならO_DIRECTを使うアプローチは?openシステムコールにO_DIRECTフラグを渡すと、ファイルへの書き込みや読み込みをVFSを介さずにファイルシステムと直接行うため、メモリにページキャッシュを残すことが無い。これは、再利用することが無いと分かっている大きなファイルを開くときには、無用にメモリを使用することが無く、他のAnonymousやFile-backedなメモリに対して優しいと言える。書き込みの際は、バッファへの書き込みが行われず、プロセスがディスクへの書き込み待ちで長い時間ブロックされることになるため注意が必要。書き込みはページキャッシュとしてメモリに蓄えられた後で非同期に(flusherスレッドによってデフォルト5秒間隔で)ディスクへ書き込まれるので、通常はプロセスが書き込みでブロックされることはない。一時的にメモリを消費してしまうものの、ディスクへ書き込んだ直後に該当のページキャッシュを解放するような仕組みがあっても良さそう。ramfsramfsはtmpfsのようにメモリ上に作成されるファイルシステムだが、ramfsの方は物理ディスクがないにも関わらず、File-backedとして登録されるため、ディスクにスワップされることがない。正常にアンマウントが実行されなかった場合には、パーティ...2015-11-05ISUCON5から学ぶいろいろISUCON5のエントリを見てるとたくさん得られることがある。仮想マシンのスタックとネットワークI/Oについて月別アーカイブ参加グループインターネットテクノロジープログラミングはてなブログをはじめよう!nishidyさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。