WSL2のVSCode Serverにメモリ制限をかける

目次

VSCodeのRemote - WSLを使っていると、vscode-serverが大量のメモリを消費することにより他のタスクに支障が出ることがある。ここでは、cgroup v2とsystemdを使ってvscode-serverに後からメモリ制限をかける方法について述べる。

環境

  • WSL 3.0.5.0
    • Ubuntu 26.04
      • systemdとcgroup v2が使えれば問題ないはず
  • VSCode 1.146.0 (system setup)
    • ms-vscode-remote.remote-wsl 1.104.7

試していないが、Remote - SSHでも同様にしてvscode-serverにメモリ制限をかけることができると思われる。

手順

  1. 必要なファイルを作成する。MemoryHigh、MemoryMax、OnUnitInactiveSecなどの数値は環境に応じて変える。

    • /etc/systemd/system/vscode_server.slice

      1[Unit]
      2Description=VSCode Server Resource Limit
      3
      4[Slice]
      5MemoryAccounting=yes
      6MemoryHigh=4G
      7MemoryMax=5G
      
    • /usr/local/sbin/vscode-server-cgroup.sh

       1#!/bin/bash
       2CGROUP="/sys/fs/cgroup/$(systemctl show vscode_server.slice -p ControlGroup --value)/cgroup.procs"
       3[[ -w "$CGROUP" ]] || exit 1
       4
       5apply_tree() {
       6        local pid=$1
       7        local child
       8        echo "$pid" > "$CGROUP" 2>/dev/null || :
       9        while read -r child; do
      10                apply_tree "$child"
      11        done < <(pgrep -P "$pid" 2>/dev/null || :)
      12}
      13
      14while read -r root; do
      15        apply_tree "$root"
      16done < <(pgrep -f '[.]vscode-server')
      
    • /etc/systemd/system/vscode-server-cgroup.service

      1[Unit]
      2Description=Move VSCode Server processes into vscode_server.slice
      3Requires=vscode_server.slice
      4After=vscode_server.slice
      5
      6[Service]
      7Type=oneshot
      8ExecStart=/usr/local/sbin/vscode-server-cgroup.sh
      
    • /etc/systemd/system/vscode-server-cgroup.timer

       1[Unit]
       2Description=Move VSCode Server processes into vscode_server.slice
       3
       4[Timer]
       5OnBootSec=1s
       6OnUnitInactiveSec=1s
       7AccuracySec=100ms
       8Unit=vscode-server-cgroup.service
       9
      10[Install]
      11WantedBy=timers.target
      
  2. sudo chmod +x /usr/local/sbin/vscode-server-cgroup.shを実行して実行権限を付与

  3. systemdユニットを有効化する

    1sudo systemctl daemon-reload
    2sudo systemctl enable --now vscode-server-cgroup.timer
    
  4. VSCodeでリモートを開く

  5. systemctl status vscode_server.sliceでプロセスがCGroupに入り、Memoryがカウントされていることを確認する

仕組み

vscode_server.sliceはcgroupを作成し、MemoryHighがソフトリミット、MemoryMaxがハードリミットを設定する。スワップも制限したければ、MemorySwapMaxを設定する。スワップについてはMemorySwapHighは実装されていない模様。

vscode-server-cgroup.shは、.vscode-serverを含むプロセスと子孫プロセスをvscode_server.sliceのcgroupに放り込むスクリプトとなっている。親プロセスをcgroupに入れても既存の子孫プロセスのcgroupは変わらないため、子孫プロセスを列挙してcgroupに放り込む必要がある。

vscode-server-cgroup.serviceはvscode-server-cgroup.shを起動するだけのoneshotサービスとなっている。vscode-server-cgroup.timerがvscode-server-cgroup.serviceを約1秒毎に起動する。

注意点

  • MemoryHighを超えるメモリが必要な場合、reclaimによりスワップアウトする場合がある。スワップが頻繁に発生することでスワップ領域のあるストレージに影響が出る可能性がある。また、メモリ確保がスロットリングされるため、パフォーマンスに影響が出る可能性がある。
  • MemoryMaxを超え、reclaimで空きを確保できなければOOMが発生する。VSCodeや拡張機能も基本的に必要があってメモリ確保をしているので、あまり低い値を設定すると使い物にならなくなる。
  • vscode-server-cgroup.shを約1秒毎に起動しているが、かえって負荷になる場合はOnUnitInactiveSecを変更して頻度を下げること。
WSL2でzramを使う