環境情報・著者紹介

swapの使用量だけで原因を決めない。状態を確認:メモリプレッシャーとプロセスを確認、swapの値だけで異常と決めない。原因を切り分ける:処理を止めて変化を確認、複数の変更を一度に加えない。対応を評価:遅延やメモリ圧迫が改善したか、再起動の効果を原因の証明にしない
macOSの管理するswapを、アプリから自由に解放できるとは限らない。

本記事は macOS Sequoia 15.7 / ComfyUI 0.3.6 / Python 3.12 で実測した内容に基づいています。著者は生成 AI(FLUX、Stable Diffusion、Llama など)をローカルで運用しており、M1 Pro で VRAM と swap のトレードオフを日常的に観測しています。


【2026-09-07 追記】macOS 26 では前提が変わっています

本記事は macOS Sequoia 15.7 時点の実測記録です。同じ M1 Pro 32GB を macOS 26.6.2(build 25G83) で測り直したところ、swap まわりの前提が変わっていました。以下の点は現行 macOS には当てはまりません。

  • swapfile の場所が変わりました。本文の ls -lh /private/var/vm/ は現行では空振りします。/private/var/vm/ に残っているのは sleepimage だけで、swapfile の実体は /System/Volumes/VM/ に移っています(両者は inode の異なる別ディレクトリで、シンボリックリンクでもありません)
  • サイズは段階拡張ではありませんでした。「1 ~ 2GB で需要に応じて増える」ではなく、観測した 3 ファイルはいずれも一律 1.0GB でした
  • 「swap ファイルは簡単には削除しない」は再検討が必要です。稼働 16 日の環境で swapfile0 / 1 / 3 が存在し、2 番だけが欠番でした。ディレクトリの更新時刻はそれより後の日付です。再起動していないのに個別に削除された可能性が高いと考えています(削除の瞬間そのものは観測しておらず、痕跡からの推定です)。そのため「対処法 1:再起動が一番確実」も、現行では前提が崩れているかもしれません
  • dynamic_pager はプロセスとして常駐していません。バイナリ・man ページ・LaunchDaemon の plist は残っていますが、pgrep dynamic_pager はヒットしません。man が既定パスとして記載している /private/var/vm/swapfile も実体と食い違っています。本文の「対処法 3」は現行では意味を持たない可能性があります
  • 「現行ラインナップ」の記述が古くなっています。M4 世代を現行として挙げていますが、その後 M5 世代が登場しています。構成とメモリ上限は Apple 公式でご確認ください

一方で、圧縮メモリ(compressed memory)の話は現行でも有効です。むしろ比重が上がっており、上記の計測では圧縮メモリが 11.99GiB(物理 32GB の約 37%)だったのに対し、swap は合計 3GB でした。「遅さの主犯は swap」という本文の力点は、現行では圧縮メモリ側に寄せて読んでください。

macOS 26 での測り直しは、あらためて別記事にまとめる予定です。


はじめに

M1 Pro 32GB の MacBook Pro で FLUX.1 schnell(画像生成モデル)をローカル実行した日、不思議なことが起きた。

  1. ComfyUI 起動、python プロセス 17GB、swap 7GB まで増える
  2. 生成 1 枚終わって ComfyUI 終了、python プロセスは消える
  3. Activity Monitor を見ると swap がまだ 7GB のまま
  4. 新しいワークロードを始める前から memory pressure がオレンジ色
  5. 次の生成時にも応答性が低下した(swap量だけを原因とは断定しない)

「使われ終わった swap は勝手に解放される」という Linux 的な直観だと説明がつかない。で、調べたら macOS の仮想メモリ設計はそもそも そういう挙動に寄っていない と分かった。

この記事は M1 Pro で生成 AI / LLM を運用していて「なんか最近遅い」と感じている人向けに、macOS の swap の特性と対処法を書き残す記録。


再現手順(簡単にできる)

Terminal で以下を実行:

sysctl vm.swapusage

実際の出力例(FLUX.1 schnell fp8 実行後):

vm.swapusage: total = 7168.00M  used = 6234.45M  free = 933.55M  (encrypted)

メモリを食うアプリ(Xcode / Docker Desktop / ComfyUI 等)を全部終了させてから同じコマンドを叩くと、used が大きく減らないまま維持されるケースがほとんど。Linux の swapoff -a && swapon -a に相当する操作は macOS には存在しない。


macOS の仮想メモリ設計

macOS の swap は Linux とは設計思想が違う。

Sequoia 15.7でのswapファイル観測(現行仕様ではない)

以下はSequoia 15.7の検証時に見たファイルとコマンド出力の記録である。macOS 26では保存場所やファイルの増減が異なったため、現在のmacOSへ一般化しない。

現行環境では、AppleのMemory Pressure説明を2026年10月9日に確認し、swap量単独ではなくMemory Pressure、圧縮メモリ、swap-in/out、実際の応答性を合わせて観察する。

Compressed Memory も絡む

macOS にはもう一つ compressed memory という仕組みがあります。

  • よく使うアプリのメモリページを圧縮して物理メモリ内に保持する
  • swap に書き出すより高速
  • 実効メモリを拡張する効果

Activity Monitor の「メモリ」タブで「圧縮」として表示されている部分です。これも 終了したアプリのメモリを即座には解放せず、しばらく圧縮状態で保持 します(次起動を速くするため)。

結果として M1 Pro で AI ワークロードを回した後は以下のような状態になります:

物理メモリ 32GB
├── アプリ使用       8GB
├── ファイルキャッシュ 5GB
├── 圧縮メモリ       7GB   ← 終了アプリの残骸
└── 空き            12GB

swap 7GB(解放されず)

「空きは十分あるじゃん」と思っても、圧縮メモリが多い状態で大きいプロセスを起動すると swap に追い出される確率が上がります。


観測方法

Memory Pressure の色

Activity Monitor の「メモリ」タブ下部に表示される graph:

  • 緑:健全(swap ほぼ未使用)
  • オレンジ:警告(重い swap 発生中)
  • 赤:危険(重大な性能劣化、システム反応鈍化)

FLUX 生成中に画面を開いたまま見ると、物理メモリ使用 + 圧縮メモリ + swap で段階的にオレンジに染まっていく様子が分かります。

vm_stat でページイン / ページアウトを見る

vm_stat 1

1 秒ごとにメモリ統計を表示。実際の出力例(FLUX 生成中):

Pageins:           245672
Pageouts:          189456
Swapins:           67890
Swapouts:          45123
Compressor pages:  1984756

注目する行:

  • Pageins:swap → 物理メモリへ読み戻す(遅くなる)
  • Pageouts:物理メモリ → swap へ退避(1 回目だけ重い)
  • Swapins / Swapouts:実際に swap ファイルを触った回数

生成中に Pageins / Swapins が継続的に増えていれば、物理メモリが足りず swap から読み戻している = 遅い状態 です。

具体的数字の例

FLUX.1 schnell fp8(8ビット浮動小数点フォーマット、fp16 より小さい)モデル(17GB)を M1 Pro 32GB で生成したときの Activity Monitor スナップショット(実測値):

python3.12:        17.57 GB    (プロセス)
メモリ使用済み:    27.11 GB / 32 GB
圧縮メモリ:        7.59 GB
swap 使用:         7.09 GB
Memory Pressure:   オレンジ

生成時間:          1 枚 203 秒

モデルを FLUX schnell GGUF Q5_K_S(llama.cpp / ggml 系の GGUF 量子化フォーマット、UNET 8GB + T5 GGUF 3GB + fp16 weights expand)に変えたら:

python3.12:        13.07 GB    (-4.5GB)
メモリ使用済み:    22 GB / 32 GB
圧縮メモリ:        2.73 GB     (-4.9GB)
swap 使用:         7.23 GB     (減らない!)
Memory Pressure:   緑

生成時間:          1 枚 173 秒(-15%)

重要な観察:swap は変わっていない(OS が保持し続けた)が、物理メモリの余裕ができたので生成時間は 15% 短縮されました。ただし速度の差が 15% に留まったのは、compute は物理メモリを小さくしただけでは縮まらない から(量子化で weight が小さくなっても演算時間は大差ない)。


対処法

1. 再起動はプロセスとメモリ状態を切り替える手段

Sequoiaの検証では再起動後にプロセスとメモリ状態が切り替わった。macOS 26ではswapファイルの場所・個別削除の挙動も異なるため、ファイル数やswap表示だけを成功条件にしない。再起動は応答性を回復する選択肢の一つであり、前後のMemory Pressure、応答性、swap-in/outを比較する。

2. sudo purge(効果限定的)

sudo purge

ファイルキャッシュを flush するコマンド。swap には効きません。圧縮メモリも大部分は残ります。実行しても体感改善は少ないため、期待値を上げないでください。

3. OS管理下のswapファイルを手動操作しない

macOSのバージョンによりswapの保存場所と管理実装は異なる。OS管理下のデーモン停止やswapファイルの削除は、再現性と安全性を確認できないため手順として掲載しない。Memory Pressureが継続して高い場合は、不要な負荷を止め、モデル・context・同時実行数を見直す。

4. ワークロード設計で避ける(最も実用的)

これが一番実用的で推奨される方法です。

モデル選択の工夫

  • GGUF 量子化モデル を優先(元の fp32 や fp16 の 30~50% 程度のサイズに圧縮)
  • fp8 フォーマット(8ビット浮動小数点、画質低下は最小限)や Q5_K_M フォーマット(Llama.cpp の標準量子化、バランス型)を選ぶ
  • フルサイズ fp16 ではなく、量子化済みモデルを活用

運用上の工夫

  • ComfyUI 系は --lowvram 相当の設定で modular load(モデル層ごとに逐次読み込み)
  • 複数の重いプロセスを同時に走らせない(LLM + 画像生成 + dev tool = 地獄)
  • 1 タスク終わったら一呼吸置いて swap が落ち着くのを待つ(効果は薄いが、心理的安定性がある)

5. 素直にメモリを増やす

Apple Silicon の現行ラインナップでは:

  • M4 Pro:最大 48GB(ここから swap が激減)
  • M4 Max / M4 Ultra:64GB / 128GB / 192GB

生成 AI を本気で触るなら M4 Pro 48GB 構成、または M4 Max 64GB 以上を検討する価値があります。ワークロードが 32GB 以内に収まっている人は問題になりませんが、複数モデルの並行実行や長時間連続実行を考えるなら 48GB 以上を強く推奨します。

→ Apple Store:MacBook Pro M4 Pro 最大 48GB でご確認ください。


LLM / 画像生成ワークロードでの観察

M1 Pro 32GB で以下を実測した体感。表内のモデルは ComfyUI デフォルト設定で実行した結果です。

モデル / ワークロード メモリ使用 初回実行 3 回目実行 備考
FLUX schnell fp8 17GB 203 秒 230 秒 当該検証で応答性低下を観測
FLUX schnell Q5_K_S GGUF 13GB 173 秒 178 秒 物理メモリ内収束、安定
SD 3.5 medium 12GB 328 秒 340 秒 fp16 weights デフォルト
Llama 3.1 70B Q4_K_M 38GB — OOM Q4_K_M は Ollama 経由

表の注釈:

  • SD 3.5 medium は ComfyUI デフォルト設定・fp16 weights を使用
  • Llama 3.1 70B は Ollama 経由の Q4_K_M(llama.cpp の k-quant 系 4bit 量子化。末尾の S / M / L はサイズと品質のグレード)で計測
  • FLUX GGUF は Q5_K_S 量子化版を使用
  • 全てのモデルは無限置換テキスト生成ではなく、単一生成(画像 1 枚またはテキスト 1 セッション)の時間

初回と3回目の差はこの検証で観測した値であり、swap量だけから原因を決めない。メモリ使用量、圧縮、I/O、温度、バックグラウンド負荷などを同時に確認する。

つまり「物理メモリに 1 ワークロード分まで収める」ことが実用性能を決める最大要因です。量子化は compute 時間より「swap しないためのメモリ削減」として効くことが多いです。


まとめ

  • swapファイルの挙動はOSバージョンで異なる。表示量だけで状態を判断しない
  • sysctl vm.swapusage と vm_stat 1 で観測できます
  • 対処はMemory Pressure、応答性、swap-in/outを見て負荷を下げる。再起動は状態を切り替える選択肢の一つ
  • ワークロードを物理メモリ内に収める のが最大の予防策です
  • 生成 AI を本気でやるなら M4 Pro 48GB / M4 Max 64GB 以上を検討する価値があります

この挙動を知っていれば「最近遅い」の原因が切り分けられます。特に複数の重い AI 系アプリを並走させている人は、一度 swap 使用量を sysctl vm.swapusage で見て、再起動前後で比較してみると納得がいくでしょう。

重いワークロードで応答性が下がるときは、swap表示だけで原因を決めず、Memory Pressure、圧縮メモリ、swap-in/out、実際の応答性を同時に観察する。


参考文献・外部資料


関連記事・おすすめ読み物

  • M4 Pro と M1 Pro の AI ワークロード比較(準備中)
  • GGUF 量子化モデルの選び方 〜 Q4_K_M vs Q5_K_S 〜(準備中)
  • ComfyUI メモリ最適化ガイド

シェア・フィードバック

この記事が役に立ったら、X(旧 Twitter)でシェアしてください。「#macOS #生成AI #メモリ管理」などのハッシュタグを添えると、同じ悩みを持つ人に届きやすくなります。

質問や改善提案は、お気軽にコメントまたは DM でお寄せください。