先日から某作業にかかりっきりでPowerShell 漬けの日々でした。 さて、その中でこれまでずっと不思議だった状況に一筋の流れが見えたので記事にしておきます。
はじまり
PowerShell = 処理速度が遅い
これは、利用した誰もが感じることであり、私自身ずっと頭を痛めている問題です。
が、海外を含めて見ると、意外とその事例が少ないと感じたのがそもそもの始まりでした。
そして、開発環境として利用していたAWS 環境 と 本番環境として同一インスタンスのAWS 環境で、同一コマンドレットを実行したのに、あからさまに処理速度が違ったことでその疑いが大きくなったのは自然な流れでした。
続報
その後、調査をしたところ、 原因の大半が Write-Progress とわかりました。
Write-Progress は完了後、 -Complete を付けて実行しないとコンソールに表示され続けます。PowerShell の動作で最も重いのがホスト表示のため一行一行の表示で WRite-Progressが出ると遅延します。
英語OSでもある程度の遅延があり増し他が、日本語表示の方はより顕著に出るようです。
現在、Wirte-Progress 処理後に、 Write-Progress -Complete を入れたことで遅延は抑えられています。V4 でやる限り Write-Host の遅延もほぼ認められないので(Console.WriteLineの方が高速ですが)、日本語環境でも安心して使えそうです。
以降はメモ記事です。無視でok。
そもそも処理速度が遅いとは
ここでいう処理速度について、どのような事を差すのかを示す必要があります。
私がこの記事で示す処理速度とはホスト画面での結果表示
つまり、処理そのものではなく、その結果をホストに表示するコストが開発環境と本番環境で劇的に違ったことが本記事の主題です。
また、描画も一度変数に入れてからその変数内容を出力すると劇的に早くなります。 ストリーム出力が遅いのが特徴です。
C# からの実行 = ホスト描画がない実行では処理速度は変わりません。
ちなみに 検証環境で 12秒で終わる処理が、本番環境で 200秒かかると言えばその程度が分かるでしょうか。。。。
とにかく描画が遅いのですが、カクカクとまったり進んだりするのです。
この遅延は、 処理方法を Workflowにしても他の高速化手法を取っても変わりません。
並列実行で開発環境では劇的に改善しても本番環境では描画の遅延により遅いままです。
開発環境と本番環境の違い
先に書いた通り、開発環境 と 本番環境は 共にAWS EC2 の m1.X1Largeインスタンスです。
OSも共に Windows Server 2012 English、PowerShell も V3.0です。
唯一の違いは、表示言語でした。 検証環境は、言語設定は英語のままでしたが、本番環境は言語設定を日本語にしていました。
さて言語が怪しいと踏んだのはいいのですが、本番環境の既定Language Pack を日本語からEnglishにしても処理速度が日本語の際同様に変わらないのです。
勿論ログオフしての適用は完了しています。
PowerShell はシステムロケール言語が日本語だと遅くなる
原因は、 ユニコード対応していないプログラムの言語 が日本語だったためでした。 英語表記だと、 Language for non-Unicode programs ですね。
ここが、English ではなく Japanese (日本語) だと、PowerShell のホスト描画処理速度が劇的に遅くなります。
例え英語OSを利用していても Japaneseだと遅いこともわかっています。
対処方法
アジアンフォントではなくしてもホスト表示が遅いのですから、フォント変換ではないことは検証で明らかになっています。
現状の打つ手としては、単純に英語OSでの実行が一番望ましいのですが、どなたかご存じなら教えてほしいモノですにゃ。
まとめ
日本語環境では PowerShell の実行は遅い。 システムロケール (ユニコード対応していないプログラムの言語) を英語にすることで、ホスト表示も含めて高速に処理されます。 PowerShell 4.0 では改善されたのかまだ試してませんね..... 近々試します。 マッタク残念記事でした。
PowerShell V4.0 で少し改善しているものの
Windows 8.1 JPN で行ったところ、一定の改善がありましたが依然として完全解決には至っていません。
PowerShell 3.0 英語ロケール : 14 sec
PowerShell 4.0 日本語ロケール : 53 sec