プロセスのCPUを制限するcpulimitを使う

はじめに

プロセスのCPU使用率を制限するcpulimitというコマンドがあるので使ってみる。

環境

Windows 11 Professional
WSL2 Ubuntu 24.04 LTS

stress-ngのインストール

stress-ngはCPU、ディスク、メモリに負荷をかけるツール

sudo apt-get install stress-ng
ログ
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  crack-common gyp libcares2 libgl1-amber-dri libglapi-mesa libjs-async libjs-events libjs-inherits
  libjs-is-typedarray libjs-prettify libjs-regenerate libjs-source-map libjs-sprintf-js
  libjs-typedarray-to-buffer libllvm17t64 liblttng-ust-common1t64 liblttng-ust-ctl5t64 liblttng-ust1t64
  libnotify-bin libqt5x11extras5 libre2-10 libssl-dev libuv1-dev libxcb-damage0 mesa-utils-bin node-abbrev
  node-ampproject-remapping node-ansi-regex node-ansi-styles node-aproba node-are-we-there-yet node-arrify
  node-async node-async-each node-auto-bind node-babel-plugin-add-module-exports node-babel7-runtime
  node-balanced-match node-base64-js node-binary-extensions node-brace-expansion node-busboy
  node-camelcase node-caniuse-lite node-chownr node-chrome-trace-event node-ci-info node-cjs-module-lexer
  node-cli-boxes node-cli-cursor node-clone node-collection-visit node-color-convert node-color-name
  node-colors node-commander node-commondir node-concat-stream node-console-control-strings
  node-convert-source-map node-core-js node-core-js-pure node-core-util-is node-data-uri-to-buffer
  node-decompress-response node-deep-is node-defaults node-define-property node-delegates node-depd
  node-diff node-electron-to-chromium node-encoding node-end-of-stream node-err-code node-error-ex
  node-es-module-lexer node-escape-string-regexp node-eslint-utils node-eslint-visitor-keys node-esquery
  node-estraverse node-esutils node-events node-fancy-log node-fast-deep-equal node-fast-levenshtein
  node-fetch node-find-up node-flatted node-foreground-child node-fs-readdir-recursive
  node-fs-write-stream-atomic node-fs.realpath node-function-bind node-get-caller-file node-get-stream
  node-get-value node-glob node-globals node-got node-graceful-fs node-growl node-has-flag
  node-has-unicode node-has-value node-has-values node-hosted-git-info node-iconv-lite node-ieee754
  node-iferr node-imurmurhash node-indent-string node-inflight node-inherits node-ini node-interpret
  node-ip node-ip-regex node-is-arrayish node-is-binary-path node-is-buffer node-is-descriptor
  node-is-extglob node-is-path-cwd node-is-plain-obj node-is-plain-object node-is-stream
  node-is-typedarray node-is-windows node-isarray node-isexe node-isobject node-js-tokens node-json-buffer
  node-json-parse-better-errors node-json-schema node-json-schema-traverse node-json-stable-stringify
  node-jsonify node-jsonparse node-kind-of node-levn node-loader-runner node-locate-path
  node-lodash-packages node-lowercase-keys node-lru-cache node-map-visit node-memfs node-merge-stream
  node-mimic-response node-minimatch node-minimist node-minipass node-mute-stream node-n3 node-negotiator
  node-npm-run-path node-object-inspect node-object-visit node-once node-optimist node-optionator
  node-osenv node-p-cancelable node-p-limit node-p-locate node-p-map node-pascalcase node-path-dirname
  node-path-exists node-path-is-absolute node-path-is-inside node-path-type node-pify node-pkg-dir
  node-postcss-value-parser node-prelude-ls node-process-nextick-args node-promise-inflight
  node-promise-retry node-promzard node-prr node-pump node-punycode node-quick-lru node-randombytes
  node-read node-readable-stream node-rechoir node-regenerator-runtime node-regenerator-transform
  node-regexpp node-regjsgen node-repeat-string node-require-directory node-require-from-string
  node-resolve node-resolve-cwd node-resolve-from node-restore-cursor node-resumer node-retry
  node-run-queue node-safe-buffer node-serialize-javascript node-set-blocking node-set-immediate-shim
  node-shebang-command node-shebang-regex node-shell-quote node-signal-exit node-slash node-slice-ansi
  node-source-list-map node-source-map node-spdx-correct node-spdx-exceptions node-spdx-expression-parse
  node-spdx-license-ids node-sprintf-js node-ssri node-stack-utils node-string-decoder node-strip-bom
  node-supports-color node-tapable node-terser node-text-table node-through node-time-stamp
  node-to-fast-properties node-tslib node-type-check node-typedarray node-typedarray-to-buffer node-undici
  node-unicode-canonical-property-names-ecmascript node-unicode-match-property-value-ecmascript
  node-unicode-property-aliases-ecmascript node-unset-value node-uri-js node-util-deprecate node-uuid
  node-v8flags node-validate-npm-package-license node-wcwidth.js node-webpack-sources node-wordwrap
  node-wrappy node-write-file-atomic node-xtend node-y18n node-yallist node-yaml nodejs-doc xbitmaps
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  libipsec-mb1 libjudydebian1 libsctp1
Suggested packages:
  lksctp-tools
The following NEW packages will be installed:
  libipsec-mb1 libjudydebian1 libsctp1 stress-ng
0 upgraded, 4 newly installed, 0 to remove and 66 not upgraded.
Need to get 2882 kB of archives.
After this operation, 21.6 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 libipsec-mb1 amd64 1.5-1build1 [1022 kB]
Get:2 http://archive.ubuntu.com/ubuntu noble/universe amd64 libjudydebian1 amd64 1.0.5-5.1build1 [107 kB]
Get:3 http://archive.ubuntu.com/ubuntu noble/main amd64 libsctp1 amd64 1.0.19+dfsg-2build1 [9146 B]
Get:4 http://archive.ubuntu.com/ubuntu noble/universe amd64 stress-ng amd64 0.17.06-1build1 [1744 kB]
Fetched 2882 kB in 4s (818 kB/s)
Selecting previously unselected package libipsec-mb1.
(Reading database ... 116802 files and directories currently installed.)
Preparing to unpack .../libipsec-mb1_1.5-1build1_amd64.deb ...
Unpacking libipsec-mb1 (1.5-1build1) ...
Selecting previously unselected package libjudydebian1.
Preparing to unpack .../libjudydebian1_1.0.5-5.1build1_amd64.deb ...
Unpacking libjudydebian1 (1.0.5-5.1build1) ...
Selecting previously unselected package libsctp1:amd64.
Preparing to unpack .../libsctp1_1.0.19+dfsg-2build1_amd64.deb ...
Unpacking libsctp1:amd64 (1.0.19+dfsg-2build1) ...
Selecting previously unselected package stress-ng.
Preparing to unpack .../stress-ng_0.17.06-1build1_amd64.deb ...
Unpacking stress-ng (0.17.06-1build1) ...
Setting up libjudydebian1 (1.0.5-5.1build1) ...
Setting up libipsec-mb1 (1.5-1build1) ...
Setting up libsctp1:amd64 (1.0.19+dfsg-2build1) ...
Setting up stress-ng (0.17.06-1build1) ...
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.6) ...

cpulimitのインストール

sudo apt install cpulimit
ログ
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  crack-common gyp libcares2 libgl1-amber-dri libglapi-mesa libjs-async libjs-events libjs-inherits
  libjs-is-typedarray libjs-prettify libjs-regenerate libjs-source-map libjs-sprintf-js
  libjs-typedarray-to-buffer libllvm17t64 liblttng-ust-common1t64 liblttng-ust-ctl5t64 liblttng-ust1t64
  libnotify-bin libqt5x11extras5 libre2-10 libssl-dev libuv1-dev libxcb-damage0 mesa-utils-bin node-abbrev
  node-ampproject-remapping node-ansi-regex node-ansi-styles node-aproba node-are-we-there-yet node-arrify
  node-async node-async-each node-auto-bind node-babel-plugin-add-module-exports node-babel7-runtime
  node-balanced-match node-base64-js node-binary-extensions node-brace-expansion node-busboy
  node-camelcase node-caniuse-lite node-chownr node-chrome-trace-event node-ci-info node-cjs-module-lexer
  node-cli-boxes node-cli-cursor node-clone node-collection-visit node-color-convert node-color-name
  node-colors node-commander node-commondir node-concat-stream node-console-control-strings
  node-convert-source-map node-core-js node-core-js-pure node-core-util-is node-data-uri-to-buffer
  node-decompress-response node-deep-is node-defaults node-define-property node-delegates node-depd
  node-diff node-electron-to-chromium node-encoding node-end-of-stream node-err-code node-error-ex
  node-es-module-lexer node-escape-string-regexp node-eslint-utils node-eslint-visitor-keys node-esquery
  node-estraverse node-esutils node-events node-fancy-log node-fast-deep-equal node-fast-levenshtein
  node-fetch node-find-up node-flatted node-foreground-child node-fs-readdir-recursive
  node-fs-write-stream-atomic node-fs.realpath node-function-bind node-get-caller-file node-get-stream
  node-get-value node-glob node-globals node-got node-graceful-fs node-growl node-has-flag
  node-has-unicode node-has-value node-has-values node-hosted-git-info node-iconv-lite node-ieee754
  node-iferr node-imurmurhash node-indent-string node-inflight node-inherits node-ini node-interpret
  node-ip node-ip-regex node-is-arrayish node-is-binary-path node-is-buffer node-is-descriptor
  node-is-extglob node-is-path-cwd node-is-plain-obj node-is-plain-object node-is-stream
  node-is-typedarray node-is-windows node-isarray node-isexe node-isobject node-js-tokens node-json-buffer
  node-json-parse-better-errors node-json-schema node-json-schema-traverse node-json-stable-stringify
  node-jsonify node-jsonparse node-kind-of node-levn node-loader-runner node-locate-path
  node-lodash-packages node-lowercase-keys node-lru-cache node-map-visit node-memfs node-merge-stream
  node-mimic-response node-minimatch node-minimist node-minipass node-mute-stream node-n3 node-negotiator
  node-npm-run-path node-object-inspect node-object-visit node-once node-optimist node-optionator
  node-osenv node-p-cancelable node-p-limit node-p-locate node-p-map node-pascalcase node-path-dirname
  node-path-exists node-path-is-absolute node-path-is-inside node-path-type node-pify node-pkg-dir
  node-postcss-value-parser node-prelude-ls node-process-nextick-args node-promise-inflight
  node-promise-retry node-promzard node-prr node-pump node-punycode node-quick-lru node-randombytes
  node-read node-readable-stream node-rechoir node-regenerator-runtime node-regenerator-transform
  node-regexpp node-regjsgen node-repeat-string node-require-directory node-require-from-string
  node-resolve node-resolve-cwd node-resolve-from node-restore-cursor node-resumer node-retry
  node-run-queue node-safe-buffer node-serialize-javascript node-set-blocking node-set-immediate-shim
  node-shebang-command node-shebang-regex node-shell-quote node-signal-exit node-slash node-slice-ansi
  node-source-list-map node-source-map node-spdx-correct node-spdx-exceptions node-spdx-expression-parse
  node-spdx-license-ids node-sprintf-js node-ssri node-stack-utils node-string-decoder node-strip-bom
  node-supports-color node-tapable node-terser node-text-table node-through node-time-stamp
  node-to-fast-properties node-tslib node-type-check node-typedarray node-typedarray-to-buffer node-undici
  node-unicode-canonical-property-names-ecmascript node-unicode-match-property-value-ecmascript
  node-unicode-property-aliases-ecmascript node-unset-value node-uri-js node-util-deprecate node-uuid
  node-v8flags node-validate-npm-package-license node-wcwidth.js node-webpack-sources node-wordwrap
  node-wrappy node-write-file-atomic node-xtend node-y18n node-yallist node-yaml nodejs-doc xbitmaps
Use 'sudo apt autoremove' to remove them.
The following NEW packages will be installed:
  cpulimit
0 upgraded, 1 newly installed, 0 to remove and 66 not upgraded.
Need to get 16.4 kB of archives.
After this operation, 49.2 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 cpulimit amd64 3.0-1 [16.4 kB]
Fetched 16.4 kB in 1s (27.9 kB/s)
Selecting previously unselected package cpulimit.
(Reading database ... 116796 files and directories currently installed.)
Preparing to unpack .../cpulimit_3.0-1_amd64.deb ...
Unpacking cpulimit (3.0-1) ...
Setting up cpulimit (3.0-1) ...
Processing triggers for man-db (2.12.0-4build2) ...

CPUlimitとは

cpulimitは、特定のプロセスのCPU使用率を制限するツール。
プロセスが設定した上限を超えるとSIGSTOPシグナルで一時停止し、CPU使用率が下がるとSIGCONTシグナルで再開する。

オプション一覧

オプション説明
-p, --pid対象プロセスのPIDを指定-p 1234
-e, --exe実行ファイル名を指定してプロセスを検索・制限-e firefox
-P, --path実行ファイルの絶対パスを指定-P /usr/bin/firefox
-b, --backgroundバックグラウンドで実行-b
-f, --foregroundフォアグラウンドで実行(デーモン化しない)-f
-c, --cpu=NマシンのCPU数検出を上書き-c 4
-l, --limitCPU使用率の上限を%で指定(必須)-l 50
-m, --monitor-forks子プロセスも監視対象に含める-m
-q, --quietエラーメッセージ以外の出力を抑制-q
-k, --killcpulimit終了時に対象プロセスを終了-k
-r, --restorecpulimit終了時に対象プロセスの優先度を復元-r
-s, --signalcpulimit終了時に送信するシグナルを指定-s SIGTERM
-v, --verbose詳細な情報を出力-v
-z, --lazyプロセス監視の間隔を長くして負荷を軽減-z
-h, --helpヘルプメッセージを表示-h

使用例

基本的な使用法

# Firefoxを起動してCPU使用率を20%に制限
cpulimit -l 20 -e firefox

# プロセスID 1234のCPU使用率を20%に制限し、終了時にSIGTERMを送信
cpulimit -l 20 -p 1234 -s SIGTERM

注意するべきところ

シグナル送信による影響

  • cpulimitは対象プロセスにSIGSTOPとSIGCONTを頻繁に送信するため、以下の問題が発生する可能性がある
    • ジョブ制御メッセージが表示される(停止/再開の通知)
    • 対話型シェルでの動作に影響する場合がある
    • フォアグラウンドジョブが意図せずバックグラウンドで実行される

プロセス検索の仕様

  • -e-Pオプション使用時は、/proc下で最初に見つかったプロセスを対象とする
  • 特定のプロセスを制御したい場合は-pオプションでPIDを指定する

使ってみる

stress-ngを使って負荷をかけてcpulimitで制限されるかを試してみる。

CPU使用率20%のプロセスを生成

# CPU使用率20%でstress-ngを実行
stress-ng --cpu 1 --cpu-load 20 &

このコマンドの説明

  • --cpu 1: CPU負荷をかけるワーカー数を1つに指定
  • --cpu-load 20: CPU使用率を20%に設定

cpulimitで制限をかける

別のターミナルでstress-ngのプロセスを制限

# stress-ngプロセスを10%に制限
cpulimit -l 10 -e stress-ng

# または、PIDを指定して制限
cpulimit -l 10 -p $(pgrep stress-ng)

Process [PID] detected と出てくるので PIDを入力する。

top -p [PID]

※この場合であれば、CPU使用率が20%以下に制限できていればOK

ログ
cpulimit -l 10 -e stress-ng
Process 7067 detected

stress-ng: info:  [7067] skipped: 0
stress-ng: info:  [7067] passed: 1: cpu (1)
stress-ng: info:  [7067] failed: 0
stress-ng: info:  [7067] metrics untrustworthy: 0
stress-ng: info:  [7067] successful run completed in 56.02 secs
[1]  + 7067 done       stress-ng --cpu 1 --cpu-load 20 --timeout 60s
Process 7067 dead!
Warning: no target process found. Waiting for it...
Process 9065 detected
Process 9065 dead!
Warning: no target process found. Waiting for it...
Process 9194 detected

参考

おわりに

今回はcpulimitを使ってみた。
プロセスごとのCPU使用率を調整するには便利そうだ。
stress-ngについては負荷をかけられるツールとして、今回使ってみたがこれも別途記事にして紹介したいと思う。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。