知識マップ: PowerShellスクリプトが遅いときに見るところ ── 配列・パイプライン・突合の勘所
記事「PowerShellスクリプトが遅いときに見るところ ── 配列・パイプライン・突合の勘所」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。
PowerShellの配列は固定長のため$array += $itemは毎回全要素をコピーし、文字列の+=も不変な文字列を毎回作り直すため、どちらも件数の2乗に比例して遅くなる。この2乗の劣化はList[T]・foreach文の出力集約・StringBuilderや-joinで避けられ、二重ループでの突合はハッシュテーブル化で線形探索の比較回数を大きく減らせる、費用対効果の最も高い改善である。Get-Contentの読み方の使い分けや遅延列挙、Get-ChildItemの-Filterによる絞り込み、Format系コマンドレットを途中に挟まないことも効果があり、これらの効果はMeasure-Commandで検証する。並列化はアルゴリズムそのものを直してから最後に検討すべき手段で、計算量がO(n^2)のまま並列化しても効果は限られる。
flowchart LR
accTitle: PowerShellスクリプトが遅い原因の知識マップ
accDescr: 配列の+=や文字列連結がもたらす2乗の速度劣化と、二重ループの突合がハッシュテーブル化やList[T]・foreach文・StringBuilderでどう軽減されるか、Get-Content・Get-ChildItem・Format系コマンドレットの使い方、Measure-Commandでの検証や並列化より先に行うべき順序の関係を示す図
array_append_antipattern["配列の+=によるコピー"]
hashtable_lookup["ハッシュテーブルによる突合"]
quadratic_slowdown["件数の2乗に比例する速度劣化"]
string_concat_antipattern["文字列の+=による再生成"]
generic_list["List[T](System.Collections.Generic.List)"]
foreach_statement["foreach文"]
stringbuilder["StringBuilder / -join"]
linear_search_matching["二重ループの線形探索による突合"]
lazy_enumeration["遅延列挙"]
get_content_cmdlet["Get-Content"]
measure_command["Measure-Command"]
get_childitem_filter["Get-ChildItemの-Filter"]
format_table["Format-Table/Format-List"]
downstream_pipeline_breakage["後続パイプラインの破壊"]
write_progress["Write-Progress"]
per_iteration_rendering_cost["進捗更新の描画コスト"]
foreach_object_parallel["ForEach-Object -Parallel"]
post_filter_discard["取得後にWhere-Objectで捨てる絞り込み"]
per_line_object_generation_cost["1行ごとのオブジェクト生成コスト"]
array_append_antipattern -->|"原因になり得る"| quadratic_slowdown
string_concat_antipattern -->|"原因になり得る"| quadratic_slowdown
generic_list -->|"軽減する"| quadratic_slowdown
foreach_statement -->|"軽減する"| quadratic_slowdown
stringbuilder -->|"軽減する"| quadratic_slowdown
hashtable_lookup -->|"軽減する"| linear_search_matching
foreach_statement -.->|"前提とする"| lazy_enumeration
get_content_cmdlet -->|"で確認できる"| measure_command
get_childitem_filter -->|"で確認できる"| measure_command
hashtable_lookup -->|"で確認できる"| measure_command
array_append_antipattern -->|"で確認できる"| measure_command
format_table -->|"原因になり得る"| downstream_pipeline_breakage
write_progress -->|"原因になり得る"| per_iteration_rendering_cost
hashtable_lookup -->|"より先に行うべき"| foreach_object_parallel
generic_list -->|"より先に行うべき"| foreach_object_parallel
foreach_object_parallel -->|"用いるのは非推奨"| quadratic_slowdown
get_childitem_filter -->|"軽減する"| post_filter_discard
get_content_cmdlet -->|"原因になり得る"| per_line_object_generation_cost
lazy_enumeration -->|"軽減する"| per_line_object_generation_cost
format_table -->|"で確認できる"| measure_command
write_progress -->|"で確認できる"| measure_command
概念間の関係(全21件)
図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。
- 配列の+=によるコピーは件数の2乗に比例する速度劣化の原因になることがあります。
- 文字列の+=による再生成は件数の2乗に比例する速度劣化の原因になることがあります。
- List[T](System.Collections.Generic.List)は件数の2乗に比例する速度劣化を軽減します。
- foreach文は件数の2乗に比例する速度劣化を軽減します。
- StringBuilder / -joinは件数の2乗に比例する速度劣化を軽減します。
- ハッシュテーブルによる突合は二重ループの線形探索による突合を軽減します。
- foreach文は遅延列挙を前提とします。
- Get-ContentはMeasure-Commandで確認できます。
- Get-ChildItemの-FilterはMeasure-Commandで確認できます。
- ハッシュテーブルによる突合はMeasure-Commandで確認できます。
- 配列の+=によるコピーはMeasure-Commandで確認できます。
- Format-Table/Format-Listは後続パイプラインの破壊の原因になることがあります。
- Write-Progressは進捗更新の描画コストの原因になることがあります。
- ハッシュテーブルによる突合はForEach-Object -Parallelより先に行うべきです。
- List[T](System.Collections.Generic.List)はForEach-Object -Parallelより先に行うべきです。
- ForEach-Object -Parallelを件数の2乗に比例する速度劣化に用いることは推奨されません。
- Get-ChildItemの-Filterは取得後にWhere-Objectで捨てる絞り込みを軽減します。
- Get-Contentは1行ごとのオブジェクト生成コストの原因になることがあります。
- 遅延列挙は1行ごとのオブジェクト生成コストを軽減します。
- Format-Table/Format-ListはMeasure-Commandで確認できます。
- Write-ProgressはMeasure-Commandで確認できます。
主要概念の定義
機械可読データ
このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。