forとforeach以外にも多用される、Foreach-Objectコマンドレット、ScriptBlock、filterを対象に測定しています。forforeachForeach-ObjectScriptBlockFilterいわずとしてれますが、PowerShellで利用する際はこのような感じです。元サイト同様の基準です。以下のいずれのデータタイプにも同じ傾向が見えます。(Array)ListArrayListForeachが最速で、次いでScriptBlock、僅差でFilter、大きく遅れてForeach-Objectです。(Slowest)実際にループで使うならどれにするか正直意外だったのは、Foreach-Objectのコストの高さです。ScriptBlockがforeachに次いで早く、Filterもほぼ同速度。Foreach-Objectは実態としてFilterだったとインアクションで読んだような気がしましたが...大きく異なる結果でした。foreachを書くのはパイプに仕込めずイラッとしますが、速度を求める場合は、Filterで代用が出来ますね。牟田口先生も、次のようにおっしゃっています。ForEach-Objectというかパイプ内のprocess{}って、コマンドレットクラスのProcessRecord()メソッドを実行していて、出力がある場合はそのメソッド内でWriteObject()メソッドを呼んでるので相当コストは高いと思います。あとForEach-Objectの場合はProcessRecord()内でscriptblockのInvokeを毎回やってるので、そのコストも高そうです。2013速度重視の場合はForEach-Object使わない方がいいかもなあ。あとパイプライン入力が重要な場合以外は。2013もっというと、配列とかコレクション|ForEach-Objectはあんまりやらないほうがよくて、コマンドレットや関数|ForEach-Objectの場合のみにする、という感じかな。process{}を実行することが重要な場合のみ利用、と。スクリプトブロックがこんなに速いってことは、ForEach-Objectが遅い理由って.NETの世界をぐるぐる回るから、ってことなんですかねー。高度な関数版も比較してみると何かわかるのかも。2013よって、ログ処理など、データが大きく単純に速度を求めてパイプに仕込まないなら......foreachデータが大きい中でパイプラインに仕込むなら......Filter単独で繰り返し実行...かつforeachr使わないようなときはさくっと......ScriptBlockオブジェクトをパイプラインを超えて渡し、速度を求めない/速度が気にならない程度の量なら......Foreach-Objectという感じでしょうか...。コレクションの大きさで実行速度は指数関数的に変化するのかコレクションの大きさでは、比例して変わるのみで指数関数的な負担にはならないようです。これなら実行速度が予想できますね。Foreachが最速で、次いでScriptBlock、僅差でFilterが状況によって入れ替わる、大きく遅れてForeach-Objectと。(Slowest)コレクションの長さが、10,100,1000,10000,100000,1000000による結果を示します。7428.81テストに利用したコード純粋にコード部分の実行速度を測るためMesure-Objectを仕込んでしまっています。キャストを含めるなら、Function全体を囲むべきなのですが。Filter実行用に予め設定します。$_}int[]に対するForループサンプルです。}}int[]に対するForeachループサンプルです。}}int[]に対するForeach-Objectループサンプルです。}}int[]に対するScriptBlockループサンプルです。}}int[]に対するFilterループサンプルです。}}実行前に、コレクションを宣言します。1..30000000実行します。$array).TotalMillisecondsコード全文です。テストに4回連続で実行しています。(CPOL)とします。2013Host出力のコスト今回は、変数に格納しているので気になりませんが、結構コストがかかります。出力値のホストへの整形表示もコスト高いですね。文字列出力を"文字列"とするのではなく、[console]::WriteLine("文字列")にすると劇的に速くなります。(9)トップへ戻るスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。