メモリレイアウト

プログラムのメモリ空間の構造で、スタック、ヒープ、コード領域、データ領域から構成される

低レベルメモリ管理

メモリレイアウトとは

プログラムのメモリ空間は、コード領域、データ領域、ヒープ、スタックの 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 }

メモリレイアウトについては関連書籍でも詳しく扱われている。

関連用語