インフラ応用編のChapter 1では、Linuxサーバ内部で実際に何が起きているのかを、 カーネル・システムコール・CPUスケジューリング・仮想メモリ・I/Oの観点から深く理解する。
単にLinuxコマンドを使える状態ではなく、CPU使用率の上昇、Load Averageの悪化、 メモリ不足、I/O Waitなどの現象について「なぜ発生しているのか」をOS内部の挙動から説明し、 ボトルネックを特定できるレベルを目指す。
1. User SpaceとKernel Space
Linuxでは、システム全体が大きく「User Space」と「Kernel Space」に分離されている。
■ User Space
一般的なアプリケーションが動作する領域である。
- Webサーバ
- データベース
- Java / Pythonなどのアプリケーション
- シェル
User Spaceのプログラムは、ハードウェアを自由に直接操作することはできない。
■ Kernel Space
OSの中核であるLinuxカーネルが動作する領域である。
- CPU管理
- メモリ管理
- プロセス管理
- ファイルシステム
- ネットワーク
- デバイス制御
アプリケーションがディスクやネットワークなどを利用するときは、 カーネルに処理を依頼する必要がある。
2. システムコールの内部構造
User SpaceのプログラムがKernel Spaceの機能を利用するためのインターフェースが System Call(システムコール)である。
代表的なシステムコールには以下がある。
- read():データの読み込み
- write():データの書き込み
- open():ファイルを開く
- close():ファイルを閉じる
- fork():プロセス生成
- execve():プログラム実行
- mmap():メモリマッピング
- socket():ソケット生成
例えばアプリケーションがファイルを読み込む場合、 概念的には以下のような処理が行われる。
Application
↓
read()
↓
System Call
↓
Linux Kernel
↓
File System
↓
Storage Device
つまり、アプリケーション性能を理解するためには、 アプリケーションコードだけではなくシステムコールまで追跡する必要がある。
3. CPUスケジューリング
実際のLinuxサーバでは、多数のプロセスやスレッドが同時に存在する。 しかし、CPUコアが一度に実行できる処理には限界がある。
そこでLinuxカーネルのSchedulerが、どのタスクにCPU時間を割り当てるかを管理する。
■ スケジューラが考慮する要素
- 実行可能なタスク数
- 優先度
- CPU使用時間
- CPUコアの負荷
- タスクの性質
大量の実行可能タスクが存在すると、 CPUを取得できず待機するプロセスが増加する。
そのためCPU使用率だけを見るのではなく、 Run Queueなども確認する必要がある。
4. Load Averageを正しく理解する
Linux運用で頻繁に利用される指標の一つがLoad Averageである。
$ uptime
load average: 2.15, 1.87, 1.43
一般的に表示される3つの値は、 直近1分・5分・15分のシステム負荷を表している。
ただし、Load Averageを単純に「CPU使用率」と考えてはいけない。 Linuxでは、CPU実行待ちだけでなく特定の割り込み不能な待機状態もLoad Averageに影響する。
したがって、Load Averageが高い場合には、 CPUだけでなくI/Oなども含めて原因を調査する必要がある。
■ CPUコア数との関係
例えば4コアCPUでLoad Averageが4前後の場合と、 1コアCPUで4の場合では意味が大きく異なる。
Load Averageは、CPUコア数やタスク状態と組み合わせて評価することが重要である。
5. 仮想メモリの内部構造
Linuxでは、各プロセスが物理メモリを直接操作するのではなく、 Virtual Memory(仮想メモリ)を利用する。
Process
↓
Virtual Address
↓
Page Table
↓
Physical Address
↓
RAM
この仕組みにより、プロセスごとに独立したアドレス空間を提供できる。
■ Page
仮想メモリはPageと呼ばれる単位で管理される。
■ Page Table
仮想アドレスと物理アドレスの対応関係を管理する。
■ TLB(Translation Lookaside Buffer)
アドレス変換結果をキャッシュすることで、 Page Tableへのアクセスを高速化する。
大規模なデータ処理では、TLB MissやPage Faultなどが 性能に影響する場合がある。
6. Page FaultとSwap
プロセスがアクセスしようとしたページが期待した状態で物理メモリ上に存在しない場合、 Page Faultが発生する。
Page Faultには、比較的低コストで処理できるものと、 ストレージI/Oを伴う高コストなものが存在する。
■ Swap
メモリが不足すると、Linuxは一部のメモリ内容をSwap領域へ退避させる場合がある。
RAM
↓
Swap
↓
SSD / HDD
ストレージはRAMより大幅に遅いため、 大量のSwap In / Swap Outが発生するとシステム性能が急激に低下する可能性がある。
そのため「メモリ使用率が高い」という数値だけではなく、 SwapやPage Faultの状態まで確認することが重要となる。
7. LinuxのPage Cache
Linuxは空いているRAMを積極的にPage Cacheとして利用する。
一度ストレージから読み込んだデータをメモリ上に保持することで、 次回以降のアクセスを高速化できる。
Application
↓
Page Cache ── HIT ──→ 高速
↓ MISS
Storage
このためLinuxでは、単純に「メモリ使用率が90%だから危険」と判断することはできない。
利用可能メモリ、キャッシュ、Swap、アプリケーションのResident Memoryなどを 総合的に確認する必要がある。
8. I/OとI/O Wait
CPUが高速でも、ストレージやネットワークからデータが届かなければ処理を進められない。
このようなI/O性能は、サーバ全体の性能を左右する重要な要素である。
■ I/O性能を見る主要指標
- IOPS:1秒あたりのI/O処理回数
- Throughput:単位時間あたりのデータ転送量
- Latency:I/O完了までの時間
- Queue Depth:I/O要求の待ち行列
CPU使用率が低いにもかかわらずアプリケーションが遅い場合、 ストレージI/Oがボトルネックになっている可能性がある。
9. CPU BoundとI/O Boundを見極める
■ CPU Bound
CPU計算能力がボトルネックになっている状態。
- 画像処理
- 暗号化
- 圧縮処理
- 大規模な計算処理
■ I/O Bound
ストレージ・ネットワーク・データベースなどのI/O待ちが ボトルネックになっている状態。
- 大量ファイルアクセス
- DBアクセス
- 外部API通信
- ネットワーク通信
性能問題を解決する際には、まずCPU BoundなのかI/O Boundなのかを切り分けることが重要である。
10. Linux性能解析ツール
Linuxには、内部状態を観測するためのさまざまなツールが存在する。
■ top / htop
top
CPU・メモリ・プロセス状態を確認する。
■ vmstat
vmstat 1
CPU、メモリ、Run Queue、Swapなどを確認する。
■ iostat
iostat -xz 1
ストレージI/Oの状態を確認する。
■ pidstat
pidstat 1
プロセス単位でCPU・I/Oなどを分析する。
■ strace
strace -p <PID>
プロセスが実行しているシステムコールを追跡する。
例えばアプリケーションが停止しているように見える場合でも、 straceによってread()やconnect()などの待機状態を確認することで、 原因をさらに深いレイヤーまで追跡できる。
11. USE Methodによる性能分析
性能問題を闇雲に調査するのではなく、 体系的に切り分けるための考え方としてUSE Methodがある。
- Utilization:リソースがどれだけ使用されているか
- Saturation:処理待ちが発生しているか
- Errors:エラーが発生しているか
CPU、メモリ、ストレージ、ネットワークなど、 主要リソースについてこの3つの観点から調査する。
CPU
├─ Utilization
├─ Saturation
└─ Errors
Memory
├─ Utilization
├─ Saturation
└─ Errors
Storage
├─ Utilization
├─ Saturation
└─ Errors
Network
├─ Utilization
├─ Saturation
└─ Errors
このような調査順序を持つことで、 「なんとなくCPUやメモリを見る」状態から脱却できる。
12. 障害解析の実践シナリオ
例えば「Web APIのレスポンスが突然遅くなった」という障害を考える。
調査では以下のようにレイヤーを分解する。
- CPU使用率とRun Queueを確認
- メモリ・Swap・Page Faultを確認
- ディスクI/OとI/O Waitを確認
- ネットワーク状態を確認
- 対象プロセスを特定
- システムコールやアプリケーションログを確認
- DBや外部サービスなど依存先を確認
重要なのは、最初から原因を決めつけないことである。
観測データから仮説を立て、 レイヤーを一つずつ切り分けながら原因を特定することが、 高度なインフラトラブルシューティングの基本となる。
13. 応用エンジニアに必要な性能設計思考
応用レベルでは、「サーバが遅い」という表現だけでは不十分である。
例えば以下のように説明できる必要がある。
- CPUが飽和しRun Queueが増加している
- 大量のMajor Page Faultによってストレージアクセスが発生している
- Swapによってメモリアクセス性能が低下している
- ストレージLatencyの増大によってI/O待ちが発生している
- システムコールの待機によってアプリケーション処理が停滞している
つまり、監視値を見るだけではなく、 「OS内部で何が起きた結果、その監視値になったのか」を説明する能力が重要となる。
まとめ
本章では、Linuxサーバの内部挙動と性能解析について学習した。
- User SpaceとKernel Spaceの境界を理解する
- システムコールによるOSとの通信を理解する
- CPUスケジューリングとLoad Averageを正しく解釈する
- 仮想メモリ・Page Fault・Swapの仕組みを理解する
- Page CacheとLinuxメモリ管理を理解する
- CPU BoundとI/O Boundを切り分ける
- Linuxツールを組み合わせて性能問題を分析する
- USE Methodによって体系的にボトルネックを特定する
これにより、Linuxサーバを単に操作するだけではなく、 カーネル・CPU・メモリ・I/Oの内部挙動から性能問題を分析できる基盤が整った。
インフラ応用編では、このレベルを出発点として、 分散システム、ネットワーク性能、データベース内部構造、 高可用性、障害解析など、より高度なシステム設計へ進んでいく。