🐧
概念 #システムパフォーマンス #Brendan Gregg #Linux #SRE #読書ノート #カーネル 📚 詳解 システム・パフォーマンス

詳解 システム・パフォーマンス - 第3章:オペレーティングシステム

Linuxカーネルの内部構造・プロセス管理・メモリ管理・スケジューラ。パフォーマンス分析のための OS 基礎知識。

なぜ OS の内部を知る必要があるか

パフォーマンス分析ツール(perf, bpftrace 等)の出力を正しく解釈するには、カーネルが何をしているかを知る必要がある。
「なぜ iowait が高いのか」「なぜ コンテキストスイッチが多いのか」は OS の仕組みを知って初めて理解できる。


カーネルの主要サブシステム

┌─────────────────────────────────────────────┐
│              ユーザー空間                     │
│   アプリケーション / シェル / ライブラリ       │
├─────────────────────────────────────────────┤
│            システムコールインターフェース        │
├──────────┬──────────┬────────┬──────────────┤
│ プロセス  │ メモリ   │ ファイル│ ネットワーク  │
│ スケジューラ│ 管理   │ システム│ スタック      │
├──────────┴──────────┴────────┴──────────────┤
│         デバイスドライバ                      │
├─────────────────────────────────────────────┤
│         ハードウェア(CPU/RAM/Disk/NIC)       │
└─────────────────────────────────────────────┘

プロセスとスレッド

状態遷移

New(作成)
  ↓ fork/exec
Runnable(実行可能)←─────────────────┐
  ↓ スケジューラが選択                 │
Running(実行中)                      │
  ↓ 時間切れ or I/O待ち               │
  ├─ Sleeping(I/O待ち / sleep)───→ Runnable
  └─ Zombie(終了待ち)

確認コマンド

# プロセス状態の確認
ps aux
# STAT列の見方:
# R: Running(実行中)
# S: Sleeping(割り込み可能スリープ)
# D: Uninterruptible sleep(I/O待ち ← ディスク問題のサイン)
# Z: Zombie
# T: Stopped

# D状態(I/O待ち)のプロセスを検出
ps aux | awk '$8 ~ /^D/ {print}'

# プロセスの詳細情報
cat /proc/<PID>/status
cat /proc/<PID>/stat     # スケジューラ統計
cat /proc/<PID>/io       # I/O統計

CPU スケジューラ

基本概念

  • タイムスライス:各プロセスが CPU を使える時間(Linux CFS では動的)
  • runキュー:実行待ちプロセスのキュー。vmstat r列 で確認
  • コンテキストスイッチ:CPU を別プロセスに渡す処理。コストがかかる

CFS(Completely Fair Scheduler)

Linux のデフォルトスケジューラ。各プロセスに「仮想実行時間」を割り当て、最も実行時間が少ないプロセスを優先する。

# コンテキストスイッチ数の確認
vmstat 1 5
# cs 列がコンテキストスイッチ数

# プロセス別コンテキストスイッチ
pidstat -w 1 5
# cswch/s: 自発的(I/O待ち等)
# nvcswch/s: 非自発的(タイムスライス切れ)

# 自発的 > 非自発的: I/O待ちが多い
# 非自発的が多い: CPU 不足で奪われている

システムコール

ユーザー空間からカーネル機能を呼び出すインターフェース。
すべての I/O・プロセス操作・ネットワーク通信はシステムコール経由

よく使うシステムコール

システムコール用途
open() / openat()ファイルのオープン
read() / write()ファイル読み書き
mmap()メモリマップドファイル
fork() / exec()プロセス生成
socket() / connect()ネットワーク
futex()スレッド間同期(ロック)
epoll_wait()I/O多重化(Webサーバー等)

syscall 分析コマンド

# プロセスの syscall を追跡(実行時間付き)
strace -c -p <PID>
# 出力例:
# % time  seconds  calls  syscall
#  60.00   0.001200   100  futex     ← ロック待ちが多い
#  30.00   0.000600    50  read
#  10.00   0.000200    20  write

# リアルタイムで syscall を見る
strace -p <PID> 2>&1 | head -30

# 特定の syscall のみ追跡
strace -e trace=open,read,write -p <PID>

# bpftrace で syscall 集計
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm, args.id] = count(); }'

メモリ管理

仮想メモリの仕組み

プロセスの仮想アドレス空間(4GB / 128TB)
┌──────────────┐
│   stack      │ ← 自動拡張(スレッドごと)
├──────────────┤
│   mmap 領域  │ ← 共有ライブラリ・匿名マッピング
├──────────────┤
│   heap       │ ← malloc() で使う領域(brk/mmap)
├──────────────┤
│   BSS/data   │ ← 初期化済みデータ
├──────────────┤
│   text       │ ← コード(読み取り専用)
└──────────────┘
         ↕ ページテーブルで変換
実際の物理メモリ(RAM)+ スワップ

ページキャッシュ

Linux はフリーメモリをディスクキャッシュ(ページキャッシュ)に使う。
free コマンドの available = free + buff/cache が使えるメモリの実態。

# ページキャッシュの状況
free -h
# → available が重要(cache は必要なら解放される)

# ページングの詳細
sar -B 1 5
# pgpgin/s: ディスクからページイン(読み込み)
# pgpgout/s: ページアウト(書き込み)
# majflt/s: メジャーページフォルト(ディスクアクセス必要)= メモリ不足のサイン

# プロセスのメモリマップ
pmap -x <PID>
# RSS が実際に物理メモリに載っている量

カーネルの観測ポイント

観測したいものツール具体的な確認方法
割り込み数cat /proc/interruptsNIC・タイマーの割り込み頻度
ソフト割り込みcat /proc/softirqsネットワーク受信処理量
カーネルパラメータsysctl -aTCP バッファサイズ等
CPU の状態cat /proc/stat生の CPU 統計
メモリの詳細cat /proc/meminfoキャッシュ・スワップの詳細
ネットワーク統計cat /proc/net/devNIC ごとの送受信量
# 割り込み数の変化をリアルタイムで監視
watch -d -n 1 'cat /proc/interrupts | head -20'

# ソフト割り込み(ネットワーク受信が多い場合に確認)
cat /proc/softirqs | grep -E "NET_RX|NET_TX"

# カーネルパラメータ確認・変更例
sysctl net.core.somaxconn        # TCP backlog キュー最大数
sysctl vm.swappiness             # スワップ積極度(0=消極的、60=デフォルト)
sysctl net.ipv4.tcp_max_syn_backlog  # SYN backlog

出典: 詳解 システム・パフォーマンス 第2版 Brendan Gregg著