知識マップ: PowerShellスクリプトが遅いときに見るところ ── 配列・パイプライン・突合の勘所

記事「PowerShellスクリプトが遅いときに見るところ ── 配列・パイプライン・突合の勘所」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。

PowerShellの配列は固定長のため$array += $itemは毎回全要素をコピーし、文字列の+=も不変な文字列を毎回作り直すため、どちらも件数の2乗に比例して遅くなる。この2乗の劣化はList[T]・foreach文の出力集約・StringBuilderや-joinで避けられ、二重ループでの突合はハッシュテーブル化で線形探索の比較回数を大きく減らせる、費用対効果の最も高い改善である。Get-Contentの読み方の使い分けや遅延列挙、Get-ChildItemの-Filterによる絞り込み、Format系コマンドレットを途中に挟まないことも効果があり、これらの効果はMeasure-Commandで検証する。並列化はアルゴリズムそのものを直してから最後に検討すべき手段で、計算量がO(n^2)のまま並列化しても効果は限られる。

PowerShellスクリプトが遅い原因の知識マップ配列の+=や文字列連結がもたらす2乗の速度劣化と、二重ループの突合がハッシュテーブル化やList[T]・foreach文・StringBuilderでどう軽減されるか、Get-Content・Get-ChildItem・Format系コマンドレットの使い方、Measure-Commandでの検証や並列化より先に行うべき順序の関係を示す図原因になり得る原因になり得る軽減する軽減する軽減する軽減する前提とするで確認できるで確認できるで確認できるで確認できる原因になり得る原因になり得るより先に行うべきより先に行うべき用いるのは非推奨軽減する原因になり得る軽減するで確認できるで確認できる配列の+=によるコピーハッシュテーブルによる突合件数の2乗に比例する速度劣化文字列の+=による再生成List[T](System.Collections.Generic.List)foreach文StringBuilder / -join二重ループの線形探索による突合遅延列挙Get-ContentMeasure-CommandGet-ChildItemの-FilterFormat-Table/Format-List後続パイプラインの破壊Write-Progress進捗更新の描画コストForEach-Object -Parallel取得後にWhere-Objectで捨てる絞り込み1行ごとのオブジェクト生成コスト

概念間の関係(全21件)

図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。

主要概念の定義

配列の+=によるコピー
PowerShellの配列が固定長であるために、要素追加のたびに新しい配列を作って全要素をコピーする書き方。
ハッシュテーブルによる突合
二重ループの中でWhere-Objectなどによる全件走査を行う突合を、索引(ハッシュテーブル)を1度だけ作りキーで引く形に置き換える高速化手法。
文字列の+=による再生成
文字列が不変(immutable)であるために、連結のたびに新しい文字列インスタンスを生成する書き方。
List[T](System.Collections.Generic.List)
要素の追加が定数時間で行える.NETの可変長コレクション型で、配列の+=の代わりに.Add()で要素を足す。
foreach文
メモリ上のコレクションを1件ずつ処理する制御構文で、1件あたりのオーバーヘッドがパイプラインより小さく、ループ全体の出力をそのまま変数に集約できる。
StringBuilder / -join
不変な文字列の+=連結を避け、可変バッファでの組み立て(StringBuilder)や配列の一括結合(-join)によって文字列連結を高速化する手段。
Get-Content
ファイルを読み込むコマンドレットで、既定では改行区切りで1行ずつオブジェクトとして返し、-Rawで一括読み込み、-ReadCountでまとめ読みができる。
Get-ChildItemの-Filter
Get-ChildItemのプロバイダーがオブジェクト取得時に適用する絞り込みパラメーターで、取得後にWhere-Objectで捨てるより効率的とされる。
Format-Table/Format-List
PowerShellの結果を画面表示用に整形するコマンドレットで、通すと結果が元のオブジェクトではなく表示用のフォーマット情報に変わる。
Write-Progress
コマンドの進行状況をホストの進捗表示として出すコマンドレットで、リダイレクト可能なデータストリームではなく、ログには残せない。
ForEach-Object -Parallel
PowerShell 7.0で追加された、入力の各要素を別のランスペースで並列実行するパラメーターセット。
遅延列挙
巨大な入力を全件メモリに読み込まず1件ずつ列挙する仕組みで、[System.IO.File]::ReadLinesなどが該当し、foreach文と組み合わせるとメモリを使わずに処理できる。

機械可読データ

このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。