新しいプロセスを作成することが、LinuxよりもWindowsで高価なのはなぜですか?


100

Windowsボックスで新しいプロセスを作成する方が、Linuxよりもコストがかかると聞きました。これは本当ですか?誰かがそれがより高価である理由の技術的な理由を説明し、それらの理由の背後にある設計決定の歴史的な理由を提供できますか?

回答:


68

mweerden:NTは最初からマルチユーザー向けに設計されているため、これは実際には理由ではありません。ただし、Unixとは対照的に、NTはマルチプロセッシングよりもマルチスレッド化を優先するため、プロセスの作成はUNIXでの場合よりもUNIXでの場合ほど重要ではありません。

Rob、COWを使用するとフォークが比較的安価であることは事実ですが、実際のところ、フォークのほとんどはexecに続いています。また、幹部はすべての画像もロードする必要があります。したがって、フォークのパフォーマンスを議論することは真実の一部にすぎません。

プロセス作成の速度について説明するときは、NTとWindows / Win32を区別することをお勧めします。NT(つまり、カーネル自体)に関する限り、プロセスの作成(NtCreateProcess)とスレッドの作成(NtCreateThread)は、平均的なUnixのように大幅に遅いとは思いません。もう少し進んでいるかもしれませんが、ここではパフォーマンスの違いの主な理由はわかりません。

ただし、Win32を見ると、プロセスの作成にかなりのオーバーヘッドが追加されていることがわかります。1つは、LPCを含むプロセスの作成についてCSRSSに通知する必要があることです。少なくともkernel32を追加でロードする必要があり、プロセスが本格的なWin32プロセスと見なされる前に、いくつかの追加の簿記作業項目を実行する必要があります。そして、マニフェストの解析、画像に互換性シムが必要かどうかの確認、ソフトウェア制限ポリシーが適用されるかどうかの確認によって課される追加のオーバーヘッドすべてを忘れないでください、yada yada。

とはいえ、プロセス、VAスペース、および初期スレッドの生の作成に加えて、実行する必要があるこれらすべての小さなことの合計の全体的な減速がわかります。しかし、冒頭で述べたように、マルチタスクよりもマルチスレッディングの方が有利であるため、この追加の費用によって深刻な影響を受けるソフトウェアは、移植が不十分なUnixソフトウェアだけです。この状況は、ChromeやIE8などのソフトウェアが突然マルチプロセッシングの利点を再発見し、頻繁にプロセスを起動および破棄するようになると変化しますが...


8
forkの後にexec()が続くとは限らず、人々はfork()だけを気にします。Apache 1.3は、Linuxではfork()(execなし)を使用し、多くの場合、プロセスが必要になる前にforkされてプールに保持されている場合でもスレッドを使用します。
Blaisorblade、2009年

5
もちろん、忘れないでください。「vfork」コマンドは、説明した「ただのexecを実行する」シナリオ用に設計されています。
Chris Huang-Leaver、

4
これによって深刻な影響受ける別の種類のソフトウェアは、複数のプロセスの調整を伴うあらゆる種類のシェルスクリプトです。たとえば、Cygwin内のBashスクリプトには、大きな問題があります。パイプラインで多くのsed、awk、grepを生成するシェルループを考えてみましょう。すべてのコマンドがプロセスを生成し、すべてのパイプがサブシェルとそのサブシェルの新しいプロセスを生成します。Unixは、このような使用法を念頭に置いて設計されたため、高速プロセスの作成が標準となっています。
Dan Molding

5
-1。ソフトウェアの「移植が不十分」であるという主張は、プロセスの作成速度を低下させる互換性の欠如でいっぱいの不十分に設計されたオペレーティングシステムでは十分に動作しないためです。
Miles Rout 2017

6
@MilesRout移植の目的は、新しいターゲットシステムで実行できるようにソフトウェアを変更することです。そのシステムの利点と欠点を考慮してください。オペレーティングシステムが提供する障害に関係なく、パフォーマンスの低い移植されたソフトウェア移植不十分なソフトウェアです
Dizzyspiral 2017

28

Unixには、現在のプロセスを2つに「分割」する「fork」システムコールがあり、最初のプロセスと同じ2番目のプロセスを提供します(forkコールからの戻りを法として)。新しいプロセスのアドレススペースはすでに稼働しているため、Windowsで「CreateProcess」を呼び出して、exeイメージや関連するdllなどをロードするよりも安価です。

フォークの場合、OSは両方の新しいプロセスに関連付けられたメモリページに「コピーオンライト」セマンティクスを使用して、それぞれが後で変更するページの独自のコピーを確実に取得できるようにします。


22
この議論は、あなたが本当にフォークしているときにだけ成り立つ。新しいプロセスを開始する場合でも、UNIXでは、フォークして実行する必要があります。WindowsとUnixの両方にコピーオンライトがあります。アプリの2番目のコピーを実行すると、Windowsは読み込まれたEXEを確実に再利用します。あなたの説明は正しくないと思います、申し訳ありません。
Joel Spolsky


回答にパフォーマンスデータを追加しました。stackoverflow.com/a/51396188/537980高速であることがわかります。
ctrl-alt-delor 2018

25

JPの発言に追加すると、ほとんどのオーバーヘッドは、プロセスのWin32スタートアップに属します。

Windows NTカーネルは、実際にはCOWフォークをサポートしています。SFU(MicrosoftのWindows用UNIX環境)は、それらを使用します。ただし、Win32はフォークをサポートしていません。SFUプロセスはWin32プロセスではありません。SFUはWin32に直交しています。どちらも同じカーネル上に構築された環境サブシステムです。

へのアウトプロセスLPC呼び出しに加えて、CSRSSXP以降では、アプリケーション互換性エンジンへのアウトプロセスコールがあり、アプリケーション互換性データベースでプログラムを検索します。この手順により、パフォーマンス上の理由から、MicrosoftがWS2003の互換性エンジン無効にするグループポリシーオプションを提供するのに十分なオーバーヘッドが発生します。

Win32ランタイムライブラリ(kernel32.dllなど)は、起動時に多くのレジストリの読み取りと初期化を行いますが、UNIX、SFU、またはネイティブプロセスには適用されません。

ネイティブプロセス(環境サブシステムなし)の作成は非常に高速です。SFUはプロセスの作成に関してWin32よりもはるかに少ないため、そのプロセスも高速に作成できます。

2019年の更新:LXSSを追加:Linux用のWindowsサブシステム

Windows 10のSFUの代替はLXSS環境サブシステムです。これは100%カーネルモードであり、Win32が持っているIPCを必要としません。これらのプロセスのsyscallは直接lxss.sys / lxcore.sysに送られるため、fork()または他のプロセスを作成する呼び出しは、作成者にシステムコールを合計1回しかかかりません。[インスタンスと呼ばれるデータ領域]は、すべてのLXプロセス、スレッド、およびランタイム状態を追跡します。

LXSSプロセスは、Win32プロセスではなく、ネイティブプロセスに基づいています。互換性エンジンのようなすべてのWin32固有のものはまったく使用されていません。


16

Rob Walkerの回答に加えて:必要に応じて、現在、ネイティブPOSIXスレッドライブラリのようなものがあります。しかし、長い間、UNIXの世界で作業を「委任」する唯一の方法は、fork()を使用することでした(そして、それは多くの状況で依然として好まれています)。例:ある種のソケットサーバー

socket_accept()
フォーク()
もし(子供)
    handleRequest()
そうしないと
    goOnBeingParent()
したがって、フォークの実装は高速である必要があり、多くの最適化が時間とともに実装されています。マイクロソフトは、新しいプロセスを作成したり、プロセス間通信を使用したりする代わりに、CreateThreadまたはファイバーさえも承認しました。CreateProcessとforkを交換することはできないため、それらを比較することは「公平」ではないと思います。fork / execをCreateProcessと比較する方がおそらく適切です。


2
最後のポイントについて:fork()はCreateProcess()と交換できませんが、Windowsがfork()を実装する必要があると言うこともできます。これにより、柔軟性が向上します。
Blaisorblade、2009年

ああ、ビーへの動詞。
acib708 2015

ただし、Linuxのfork + execは、MS-WindowsのCreateThreadより高速です。そして、Linuxはそれだけでフォークを実行してさらに高速化できます。どのように比較しても、MSは遅いです。
ctrl-alt-delor 2018年

13

この問題の鍵は、両方のシステムの歴史的な使用法だと思います。Windows(およびその前のDOS)は、もともとパーソナルコンピュータのシングルユーザーシステムでした。そのため、これらのシステムは通常、常に多くのプロセスを作成する必要はありません。(非常に)簡単に言うと、プロセスは、この1人の孤独なユーザーが要求したときにのみ作成されます(そして、私たち人間は、比較的高速に動作しません)。

Unixベースのシステムは、もともとマルチユーザーシステムとサーバーでした。特に後者の場合、特定のジョブを処理するためにプロセスを分割するプロセス(たとえば、メールまたはhttpデーモン)を使用することは珍しくありません(たとえば、1つの着信接続を処理します)。これを行う際の重要な要素は安価なfork方法です(Rob Walker(47865)が言及したように、最初は新しく作成されたプロセスに同じメモリを使用します)。これは、新しいプロセスが必要なすべての情報をすぐに保持するので非常に便利です。

少なくとも歴史的には、UNIXベースのシステムが高速なプロセスを作成する必要性は、Windowsシステムの場合よりもはるかに大きいことは明らかです。Unixベースのシステムは依然として非常にプロセス指向であり、Windowsはその歴史上、おそらくスレッド指向である(スレッドは応答性の高いアプリケーションの作成に役立つ)ため、これは依然として当てはまると思います。

免責事項:私は決してこの問題の専門家ではないので、私がそれを間違えた場合、私を許してください。


9

ええと、進行中の正当化の多くの「それはこの方法の方がいい」のようです。

人々は「Showstopper」を読むことから利益を得ることができると思います。Windows NTの開発に関する本。

サービスがWindows NTの1つのプロセスでDLLとして実行される理由は、それらが個別のプロセスとしては遅すぎるためです。

落ちて汚い場合は、ライブラリのロード戦略に問題があることがわかります。

Unices(一般的に)では、共有ライブラリ(DLL)のコードセグメントが実際に共有されます。

Windows NTは、ロード後にライブラリコードセグメント(および実行可能コードセグメント)を操作するため、プロセスごとにDLLのコピーをロードします。(あなたのデータはどこにあると言いますか?)

これにより、再利用できないライブラリのコードセグメントが生成されます。

したがって、NTプロセスの作成は、実際にはかなり高価です。そしてマイナス面としては、DLLがメモリを大幅に節約することはできませんが、アプリ間の依存関係の問題が発生する可能性があります。

時々、エンジニアリングに戻り、「今、本当にこれを吸うようにこれを設計しようとすると、それはどのように見えるでしょうか?」

むかしむかしむかしむかれた組み込みシステムを使用していたところ、ある日それを見て、マイクロ波空洞に電子機器を備えた空洞マグネトロンであることに気付きました。その後、私たちはそれをはるかに安定させました(そして電子レンジのようにはなりませんでした)。


3
DLLが優先ベースアドレスでロードされる限り、コードセグメントは再利用できます。従来は、プロセスにロードされるすべてのDLLに競合しないベースアドレスを設定する必要がありますが、ASLRでは機能しません。
マイクディミック

すべてのDLLをリベースするツールはありますか?ASLRでそれが何をするかわかりません。
Zan Lynx

3
コードセクションの共有は、ASLR対応システムでも機能します。
ヨハネスが

@MikeDimmickなので、DLLを作成するすべての人が協力して、競合がないことを確認する必要がありますか、それとも、ロードする前にシステムレベルですべてにパッチを適用しますか?
ctrl-alt-delor

9

短い答えは「ソフトウェア層とコンポーネント」です。

Windows SWアーキテクチャには、Unixには存在しないか、単純化されてUnixのカーネル内で処理される追加のレイヤーとコンポーネントがいくつかあります。

Unixでは、forkとexecはカーネルへの直接の呼び出しです。

Windowsでは、カーネルAPIは直接使用されず、その上にwin32と他の特定のコンポーネントがあるため、プロセスの作成は追加のレイヤーを通過し、新しいプロセスが起動するか、それらのレイヤーとコンポーネントに接続する必要があります。

かなり長い間、研究者や企業は漠然と同様の方法でUnixを解体しようとしましたが、通常は実験をMachカーネルに基づいています。よく知られている例はOS Xです。しかし、彼らが試みるたびに非常に遅くなり、少なくとも部分的にカーネルに部分的にマージすることになります。これは、永続的または製品出荷のためです。


レイヤーは必ずしも処理速度を低下させるわけではありません。多くのレイヤーを備えたデバイスドライバーをCで記述しました。コードは簡潔で、読み書きが簡単で、読みやすいです。レイヤーなしの高度に最適化されたアセンブラーで記述されたバージョンよりも(わずかに)高速でした。
ctrl-alt-delor 2018

皮肉なことに、NTは巨大なカーネル(マイクロカーネルではない)です
ctrl-alt-delor

2

いくつかの回答でMS-Windowsの正当化があるように見えるので、例えば

  • 「NTカーネルとWin32は同じものではありません。NTカーネルにプログラムする場合、それはそれほど悪くありません」— True、しかし、Posixサブシステムを作成しているのでない限り、誰も気にかけません。win32に書き込みます。
  • 「フォークとProcessCreateを比較することは公平ではありません。それらは異なることを行い、Windowsにはフォークがないためです。」— Trueなので、like likeと比較します。ただし、フォークも比較します。フォークには、プロセスの分離などの多くの使用例があるためです(たとえば、Webブラウザーの各タブは異なるプロセスで実行されます)。

事実を見てみましょう。パフォーマンスの違いは何ですか?

http://www.bitsnbites.eu/benchmarking-os-primitives/から要約されたデータ
バイアスは避けられないため、要約すると、ほとんどのテストではi7 8コア3.2GHz のMS-Windows ハードウェアを優先しました
。Gnu / Linuxを実行するRaspberry-Piを除く

Gnu / Linux、Apple-Mac、およびMicrosoftのWindowsでのさまざまな基本操作の比較(小さいほど良い)

MS-Windowsプロセス作成とLinuxの比較

注:Linuxでは、forkMS-Windowの推奨される方法よりも高速ですCreateThread

プロセス作成タイプの操作の数(グラフではLinuxの値を確認するのが難しいため)。

速度の速いものから遅いものへ(数値は時間であり、小さいほど良い)。

  • Linux CreateThread 12
  • Mac CreateThread 15
  • Linuxフォーク19
  • Windows CreateThread 25
  • Linux CreateProcess(fork + exec)45
  • Macフォーク105
  • Mac CreateProcess(fork + exec)453
  • Raspberry-Pi CreateProcess(fork + exec)501
  • Windows CreateProcess 787
  • Windows CreateProcess with Virus Scanner 2850
  • Windowsフォーク(CreateProcess + fixupでシミュレート)2850以上

他の測定の番号

  • ファイルを作成します。
    • Linux 13
    • Mac 113
    • ウィンドウズ225
    • Raspberry-Pi(遅いSDカードを使用)241
    • Defenderおよびウイルススキャナーなどを備えたWindows 12950
  • メモリの割り当て
    • Linux 79
    • Windows 93
    • Mac 152

1

これらすべてに加えて、Winマシンでは、おそらくウイルス対策ソフトウェアがCreateProcess中に起動するという事実があります...これは通常、最大のスローダウンです。


1
はい、それは最大ですが、唯一の重大な減速ではありません。
ctrl-alt-delor

1

また、WindowsのセキュリティモデルはUNIXベースのOSよりもはるかに複雑であるため、プロセスの作成中に多くのオーバーヘッドが発生することにも注意してください。Windowsのマルチプロセッシングよりもマルチスレッド化が好まれるもう1つの理由。


1
より複雑なセキュリティモデルの方が安全であると思います。しかし、事実はそれ以外を示しています。
ライライアン

4
SELinuxは非常に複雑なセキュリティモデルでもあり、fork()
Spudd86に

6
@LieRyan、(私の経験では)ソフトウェア設計では、より複雑になることは非常にまれに、より安全であることを意味します。
Woodrow Douglass 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.