メモリレイアウト
プログラムのメモリ空間の構造で、スタック、ヒープ、コード領域、データ領域から構成される
低レベルメモリ管理
メモリレイアウトとは
プログラムのメモリ空間は、コード領域、データ領域、ヒープ、スタックの 4 つの領域で構成される。JavaScript 開発者が直接操作することは少ないが、パフォーマンスやメモリリークの理解に重要。
メモリ領域
高アドレス ┌──────────────┐
│ スタック ↓ │ ← 関数の引数、ローカル変数
│ │
│ ↓ 成長方向 │
│ │
│ ↑ 成長方向 │
│ │
│ ヒープ ↑ │ ← 動的に確保されるオブジェクト
├──────────────┤
│ データ領域 │ ← グローバル変数、定数
├──────────────┤
│ コード領域 │ ← 実行可能なコード
低アドレス └──────────────┘
| 領域 | 内容 | 管理 |
|---|---|---|
| スタック | 関数の引数、ローカル変数 | 自動 (LIFO) |
| ヒープ | オブジェクト、配列、文字列 | GC or 手動 |
| データ | グローバル変数、定数 | コンパイル時に確定 |
| コード | 実行可能な命令 | 読み取り専用 |
スタック vs ヒープ
| 観点 | スタック | ヒープ |
|---|---|---|
| 速度 | 高速 (ポインタ移動のみ) | 低速 (アロケーション) |
| サイズ | 小さい (数 MB) | 大きい (数 GB) |
| 管理 | 自動 (関数終了で解放) | GC or 手動 |
| 格納データ | プリミティブ、参照 | オブジェクト、配列 |
V8 (Node.js) のメモリ
// スタック: プリミティブ値と参照
const x = 42; // スタックに 42 を格納
const obj = { a: 1 }; // スタックに参照、ヒープにオブジェクト
// ヒープ: オブジェクト
// V8 のヒープは Young Generation と Old Generation に分かれる
Lambda の MemorySize はヒープ、スタック、OS のオーバーヘッドを含む。CPU も比例して割り当てられるため、メモリを増やすと処理速度も向上する。
スタックオーバーフロー
// ❌ 無限再帰 → スタックオーバーフロー
function infinite(): number { return infinite(); }
// RangeError: Maximum call stack size exceeded
// ✅ 末尾再帰最適化 (一部の環境) or ループに変換
function factorial(n: number, acc = 1): number {
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
メモリリークの検出
# Node.js のヒープ使用量を確認
node -e "console.log(process.memoryUsage())"
# { rss: 30MB, heapTotal: 7MB, heapUsed: 5MB, external: 1MB }
メモリレイアウトについては関連書籍でも詳しく扱われている。