LoginSignup
3
3

More than 1 year has passed since last update.

Windowsプロセス間通信の速度比較

Posted at

Windowsプロセス間通信の速度比較

Windows環境でのプロセス間通信では、一体どういった構築がベストなのか、資料を見つけられなかったので適当に測定してみました。
こういうのは環境によるところが多いので、常に使えるデータではありませんが、一つの参考にはなるかもしれません。

測定環境:Windows10 / Rysen5-5600X / SSD2TB / メモリ64GB

※ Debugビルドしかしていないし、全くもって厳密な測定ではありません…

調べたい項目

  • プロセスの起動速度
  • 通信手法
  • 転送バッファサイズと転送速度の関係

プロセスを新規に起動してそれに対してプロセス間通信を行う、という処理一式の軽量さを判断したいので、プロセス自体の起動速度も比較対象に含めました。

より詳細な比較項目

  • SubSystem:Console vs SubSystem:Windows
  • 匿名パイプ vs 共有メモリ(=メモリマップトファイル)
  • 小さいバッファサイズで細切れに転送 vs 大きいバッファサイズで一度に転送

通信手法については、名前付きパイプ・ソケット通信・ファイルで通信 などは速度面から不利であることが分かっているので、検証対象から外しました。

一般的には共有メモリがダントツで早いと言われていますが、Windowsのそれはメモリマップトファイルであり、メモリにキャッシュはされるもののストレージのアクセス速度が足を引っ張る可能性があります。

測定方法

  1. 子プロセスを起動
  2. 匿名パイプで、親から子にデータ要求を出す
  3. 匿名パイプ or 共有メモリ で、子から親にBlockSize分のデータを渡す
  4. 親が累計TotalSize分のデータを受け取ったら終了。まだなら2に戻る

以上を SubSystem:Console の場合と SubSystem:Windows の場合で行う。

結果

プロセス起動処理にかかる時間は

Console 匿名パイプ Windows 匿名パイプ Console 共有メモリ Windows 共有メモリ
一度目 17ms 2ms 17ms 2ms
以降 2ms 2ms 2ms 2ms

転送処理にかかる時間は、TotalSize:1GB のとき

Console 匿名パイプ Windows 匿名パイプ Console 共有メモリ Windows 共有メモリ
BlockSize:32KiB 430ms 500ms 500ms 440ms
BlockSize:64KiB 250ms 290ms 370ms 315ms
BlockSize:128KiB 150ms 175ms 245ms 230ms
BlockSize:256KiB ★ 130ms 130ms 130ms 135ms
BlockSize:512KiB 200ms 200ms ☆ 115ms 130ms
BlockSize:1MiB 410ms 430ms 485ms 490ms
BlockSize:4MiB 450ms 565ms 470ms 480ms
BlockSize:8MiB 620ms 690ms 515ms 505ms
BlockSize:16MiB 760ms 820ms 715ms 700ms
BlockSize:32MiB 1045ms 1090ms 950ms 930ms

考察

プロセス起動にかかる時間について

SubSystem:Consoleの場合はコンソールウィンドウに標準出力をアタッチしたりなんなりとかのコストがかかるでしょうから、 SubSystem:Windows の方が早いのは理解できます。連続して何度も呼んだ場合は何かしらのキャッシュに乗るのか、WindowsでもConsoleでも同じ2msになりました。

転送処理にかかる時間について

Subsystemは関係ないだろうと思っていたのですが、おおむね(特に匿名パイプは)Consoleの方が早いという結果が出ました。原因は分かりません。(誤差かもしれません)

共有メモリは僅かに早いケースもあるものの、匿名パイプとほぼ変わらないという結果になりました。
もしかしたら読み込みの同期に匿名パイプを併用する必要がある以上、その同期に時間が掛かってしまって速さを発揮できていないのかもしれません。ただ同期は絶対に必要なので、やはり結果的にはWindowsの共有メモリによる通信は匿名パイプとほぼ変わらないと言えるかもしれません。
少なくとも「共有メモリがダントツで早い」というイメージからはほど遠いですね…。

総評としては

Subsystem:Console の方がスタンドアロンでのテストが行いやすいというメリットがあるので、同じイメージファイルで何度もプロセスを立ち上げるのであればほぼ速度は変わらないですし、メンテナンス性の観点からConsoleにした方がよさそうです。

また共有メモリは途中で例外が起きたりしてうっかり開放をしそびれると、再起動まで永久に無駄ファイル&メモリが残り続ける恐れがあります。
そういう扱いが危険な代物でもあるので、早さの違いがほぼないのであれば選択するメリットはないでしょう。

使用すべきブロックサイズは環境にもよるでしょうが、とりあえず表から見て256KiBあたりが良いであろうことは分かります。

結論

今回のケースでは

  • Subsystem:Console
  • BlockSize:256Kib
  • 通信方式:匿名パイプ

とするのが良いかなという結論が得られました。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3