PowerShellの起動を速くする

PowerShellのコンソールを起動すると普通のコマンドラインに比べて起動が遅いなと感じる。これは.NETの性質に由来するもので、MSIL(中間言語)を実行時にJIT(Just in Time)コンパイルするためである。実行時に機械言語へのコンパイルを行っているのだ。このJITコンパイル方式はあらゆるCPUやOSに対応させるためにインタプリタの利点を生かしたまま実行時には機械言語の処理速度を保てるという利点がある。

でも考えても見るとPowerShellが必要な環境では多種のOSで動く必要が今のところはない。速く起動してくれるに越したことはないのだ。それを実現するためにはMSILをすでに機械言語にコンパイルさせていればその実行時にその過程が不必要になるために速くなる。.NET Frameworkにはngenというのがあってこれを使うと事前コンパイルを可能にしてくれる。

ネイティブ イメージ ジェネレータ (Ngen.exe) は、マネージ アプリケーションのパフォーマンスを向上するツールです。Ngen.exe は、コンパイルされたプロセッサ固有のマシン コードを含むファイルであるネイティブ イメージを作成してローカル コンピュータのネイティブイメージ キャッシュにインストールします。ランタイムは、JIT (Just-In-Time) コンパイラを使用してオリジナルのアセンブリをコンパイルする代わりに、キャッシュにあるネイティブ イメージを使用できます。(MSDNより

 

そのngenを使って実際に起動を速くするスクリプトがPowerShell Team Blogに載っていたので下に抜粋しておく。

Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

上のスクリプトを.ps1ファイルに保存してPowerShellから実行してPowerShellのコンソールを起動してみると、起動が数倍速くなっている。ぜひ試してみてほしい。

コメント

  1. HIRO より:

    NGEN確かに使えますね。
    これでPowerShellの起動が速くなるならやっておいた方が良いですね。

    NgenはPowerShellだけでなく、.NETで作成したアプリには有効ですから、これを機に覚えておきたい技ですね。

    過去に
    http://hiros-dot.net/CS2003/Environment/Environment06.htm
    に書いたことがあります。(あまりたいしたこと書いてないですが(..;))
    御参考まで

  2. _ より:

    なお本来はインストール時に自動的にngenがかかるべきだったようで、現在では修正されているため手動ngenの必要はなさそうです。

    > NOTE – this is a workaround for a V1 bug. This is fixed in V2.
    https://blogs.msdn.microsoft.com/powershell/2008/09/02/speeding-up-powershell-startup-updating-update-gac-ps1/

    上記ページのスクリプトのようにRuntimeEnvironment.FromGlobalAccessCache()を使ったり、あるいは次のようにアセンブリを一覧表示するだけでも、LocationがGACのディレクトリを指していることが確認できます。

    [AppDomain]::CurrentDomain.GetAssemblies()

    (だいぶ前の記事ですが、最近になって言及されていたので参考までに)

タイトルとURLをコピーしました