読者です 読者をやめる 読者になる 読者になる

tom__bo’s Blog

情報系学生が筋トレしたり、筋トレしたり筋トレしたことを書くブログ。もはやダイアリー

Systems Performance 読んでいく (7章 その1)

SystemsPerformance Performance Linux Book

Systems Performance: Enterprise and Cloudを読んでいく。

前回の続き。
7章2節まで。

7 Memory

システムのメインメモリはアプリケーションやカーネル命令、それらの実行中のデータやファイルシステムのキャッシュなどを保管している。 多くの場合、これらのデータはディスクに保存されている。 メインメモリがいっぱいになった場合はディスクとのやり取りが発生するが、ディスクはメモリに比べて非常に遅いので、よくパフォーマンス上の問題になる。

他のパフォーマンス上の問題としてはメモリに配置したり、開放する際のCPUコストやメモリのコピー、メモリのアドレススペースのマッピング管理などがある。 また、マルチソケットアーキテクチャではメモリのローカリティがよく問題になる。

7.1 Terminology

この章で扱うメモリ関連の用語を紹介する。

  • Main memory
    • "physical memory(物理メモリ)"とも書く。
    • コンピュータに置いて高速なストレージ。大抵DRAMによって提供される。
  • Virtual memory
    • 仮想的なメインメモリ
    • ほぼ無限でコンテンツを持たない(noncontented)
  • Resident memory
    • 現在メインメモリに存在するメモリ
  • Anonymous memory
    • ファイルシステム上の場所やパス名のないメモリ。
    • ヒープと呼ばれるプロセスのアドレススペースにある、実行中のデータ等
  • Address space
    • モリーコンテキスト。
    • カーネルとそれぞれのプロセスごとにある仮想のアドレススペース
  • Segment
    • 特定の目的で確保されたメモリ領域
  • OOM
    • "out of memory"
    • 利用可能なメモリが少ないとカーネルが検出した時に起こる
  • Pagefault
    • 無向なメモリアクセス。
    • "on-demand"な仮想メモリを使っていると普通に起こる
  • Pageng
    • メインメモリとストレージ間でのページの移動
  • Swapping
    • anonymous dataやスワップされたプロセスのためのディスク上の領域。
    • これらは大抵ストレージデバイス上にあり、"physical swap debice"やファイルシステム上にあれば"swapfile"と呼ばれる。
    • いくつかのツールは"swap"という用語を仮想メモリとして使っているが、これは誤用

7.2 Concept

この節ではメモリとメモリのパフォーマンスに関する重要な概念を紹介する。

7.2.1 Virtual memory

仮想メモリはそれぞれのプロセスや、線形でプライベート空間を持ったカーネルを提供する、抽象的なメモリ空間である。 これはOSが管理している物理的なメモリを単純化してくれる。 また、仮想アドレス空間はデザインとして分離されているので、マルチタスク処理が可能で、更に実際のメインメモリより多くの空間を扱える。

図7.1はプロセスにおける仮想メモリの役割を示している。 ここでは多くの実装がページベースであることからメモリの1つのページを示している。

図7.1 f:id:tom__bo:20161215223904p:plain

プロセスんおアドレススペースは仮想メモリとしてメインメモリとswapデバイスにマッピングされている。 カーネルは必要に応じてこれらの間でページを移動でき、これを"paging"という。 この仕組みによってカーネルは"oversubscribe"(メインメモリの領域より多くのアドレスを使うこと)ができる。

7.2.2 Paging

ページングはメインメモリからページが出たり入ったりする移動のことである。
これによって以下のことができるようになる。

  • 実行するプログラムを部分的にロードする
  • メインメモリよろ大きいサイズのプログラムを実行する
  • メインメモリとストレージデバイス間での効率的なプログラムの移動。

これらは現在でも有効な技術である。

スワッピングがプログラム全体を移動するのと違い、ページサイズが比較的小さく設定されているので、メインメモリの管理の面でよく出来ている。 仮想メモリを使うページング"paged virtual memory"は、BSDからUnixに取り入れられ、標準になった。 このあと、共有ファイルシステムのページのためのページキャシュが加えられ、2つの種類のページングが利用可能になった。"file system paging"と"anonymous paging"である。

[File System Paging]

ファイルシステムページングはメモリにマップされたページを読み書きすることで起こる。 これはメモリマッピング(mmap)を使うアプリケーションの普通の振る舞いである(詳細は8章へ)。 カーネルがページを解放するとき、メインメモリのページに書き込みがある"dirty"な状態なときはディスクに内容を書き出す必要があるが、書き込みがない"clean"な時はディスクに情報があるので、ただ解放すれば良いことになる。

[Anonymous Paging]

Anonymousページングはプロセスヒープやスタックといった、プロセスに対してプライベートなデータを含む。 "anonymous"という名前が付いているのは、これにOS上の(パス名などの)場所の名前がないからである。Anonymousページで追い出されたデータはswapデバイス化スワップファイルに書き出される。これをLinuxでは"swapping"と呼ぶこともある。

Anonymousページングはパフォーマンスのあ悪化を招くので、悪いページングと言える。 Anonymousページング(in)が発生することで、ディスクからの読み込みが問題となる。ページアウト(out)は非同期で実行される場合は直接の問題にはならない。 パフォーマンス上はAnonymousページングがない状態が最善なので、アプリケーション側で調整できることが望ましい。

7.2.3 Demand Paging

デマンドページングは図7.2に示すように、仮想メモリから物理メモリへのマッピングを必要なときに(ondemandで)行う。 これは実際に書き込みのアクセスがあるまで割当をしないことで、CPUのオーバーヘッドを延期する。

図7.2 f:id:tom__bo:20161215223921p:plain

図7.2では、仮想メモリへの新しいアドレスに書き込みが発生することで、物理メモリへのondemandな配置が発生している。個々で仮想から物理のページヘのマッピングがないので、"page fault"が発生する。これはreadから始まることもある。

この要求がメインメモリ内にあった場合は、"minor fault"といい、ディスクアクセスが必要なものだった場合は"major fault"という。

仮想メモリモデルとデマンドアロケーションに酔って、仮想メモリ内のページは以下のどれかの状態になる。

  1. アロケートされていない
  2. アロケートされているが、マッピングされてない
  3. アロケートされていて、メインメモリにマッピングされている
  4. アロケートされていて、swapデバイスにある

これらの状態から2角用語が定義されている。

  • Resident set size(RSS)
    • メインメモリに有ろけーとされたページのサイズ(3)
  • Virtual memory Size
    • 全てのアロケートされている領域のサイズ(2+3+4)

7.2.4 Overcommit

オーバーコミットによって物理的なメモリとスワップバイスの合計より多くの領域を使うことができる。 これは、デマンドページングの技術と、アプリケーションが割り当てた領域の全てを使わないという傾向によってできている。

オーバーコミットはチューニング可能なパラメータとして、7.6節でも紹介する。

7.2.5 Swapping

スワッピングはプロセス全体をメインメモリと物理デバイス間で移動することである。 これはUnix由来の技術で、"swap"という用語の起源である。

スワッピングではプロセスに関連する全てのデータをディスクに移すことになる。 スワップアウトしたプロセスのデータはカーネルメタデータとして保持しているので、必要なときに呼び出すことができるが、ディスクI/Oを伴うのでパフォーマンス悪化の原因となる。

"システムがスワップしている"という時は、たいていページングを指している。Linuxではswappingはページング(anonymous paging)を意味している。

7.2.6 File System Cache Usage

メインメモリが余っているなら有効に使おうという目的で、ファイルシステムのデータをメモリにキャッシュすることでパフォーマンスを向上している。

7.2.7 Utilization and Saturation

メインメモリの使用率は、使っているメモリと全メモリで計算される。 ファイルシステムキャッシュで使われているメモリはアプリケーションによって再使用可能なのでunusedとして扱われる。メインメモリの容量を超えてメモリを要求した場合、メモリは"saturated"な状態であり、OSはメモリを開放するためにページングやスワッピング、LinuxであればOOM(後述)を行う。これらの活動は全てメモリのサチュレーションを示している。

また、仮想メモリもキャパシティベースの使用率で考えることができ、サチュレーションも起きる(オーバーコミットではない)。 もし仮想メモリが枯渇した場合、malloc()であればENOMEMを返す。 "現在利用可能な仮想メモリ"は時々、紛らわしいことに"available swap"と呼ばれるので注意する。

7.2.8 Allocators

仮想メモリが物理メモリをマルチタスクで扱っている一方で実際のアロケーションはアロケータによって行われる。これらはユーザライブラリやカーネルルーチンとして簡単なインタフェースを提供している(malloc()やfree()など)アロケータはパフォーマンスに重大な影響を与える。システムは複数のユーザレベルアロケータライブラリを提供している。 これらの特殊な例は7.3節で網羅される。

7.2.9 Word Size

6章CPUで紹介したようにプロセッサにはワードサイズがある。32bitアーキテクチャではメモリは4GBしか使えないので、大抵は64bitのアーキテクチャが必要である。