Powershell文字列の最適化

入門:このメモでは、Stringの代わりにStringBuilderオブジェクトを使用して多数の文字列を処理するときに5〜10(またはそれ以上)の加速を得る方法について説明します。

System.Text.StringBuilderコンストラクターの呼び出し:

$SomeString = New-Object System.Text.StringBuilder 

文字列の逆:

 $Result = $Str.ToString() 

多くのテキストファイルを処理するスクリプトを作成する際に、PowerShellで文字列を操作する特性が発見されました。つまり、標準の文字列オブジェクトを使用して文字列を処理しようとすると、解析速度が大幅に低下します。

初期データ-タイプごとの行で詰まったファイル:

key;888;0xA9498353,888_FilialName


スクリプトの未加工バージョンでは、処理を制御するために中間テキストファイルが使用されました。1000行のファイルの処理時間の損失は24秒で、ファイルサイズが大きくなると、遅延が急激に増加します。 例:

 function test { $Path = 'C:\Powershell\test\test.txt' $PSGF = Get-Content $Path #   $PSGFFileName = $Path + '-compare.txt' Remove-Item -Path $PSGFFileName -ErrorAction SilentlyContinue | Out-Null New-Item $PSGFFileName -Type File -ErrorAction SilentlyContinue | Out-Null # ToDo #     ,  . #     Add-Content,    foreach ($Key in $PSGF) { $Val = $Key.ToString().Split(';') $test = $val[2] $Val = $test.ToString().Split(',') $test = $Val[0] Add-Content $PSGFFileName -Value $Test } $Result = Get-Content $PSGFFileName Remove-Item -Path $PSGFFileName -ErrorAction SilentlyContinue | Out-Null ###    # end ################################ return $Result } 

実行結果:

99行-1.8秒
1000行-24.4秒
2000行-66.17秒

最適化番号1


明らかに、これは良くありません。 ファイルへのアップロードをメモリ内の操作に置き換えます。

 function test { $Path = 'C:\Powershell\test\test.txt' $PSGF = Get-Content $Path $Result = '' # foreach ($Key in $PSGF) { $Val = $Key.ToString().Split(';') $test = $val[2] $Val = $test.ToString().Split(',') $test = $Val[0] $Result = $Result + "$test`r`n" } return $Result } Measure-Command { test } 

実行結果:

99行-0.0037秒
1000行-0.055秒
2000行-0.190秒

すべてがうまくいくようで、加速が得られますが、オブジェクトにさらに行がある場合はどうなるか見てみましょう:

10,000行-1.92秒
20,000行-8.07秒
40,000行-26.01秒

この処理方法は、5〜8千行以下のリストに適しています。その後、オブジェクトのコンストラクターで損失が始まり、メモリマネージャーは行を追加するときに常に新しいメモリを割り当て、オブジェクトをコピーします。

最適化№2


「プログラマー」アプローチを使用して、より良いことを試みましょう。

 function test { $Path = 'C:\Powershell\test\test.txt' $PSGF = Get-Content $Path #     $Str = New-Object System.Text.StringBuilder foreach ($Key in $PSGF) { $Val = $Key.ToString().Split(';') $temp = $val[2].ToString().Split(',') $Val = $temp $temp = $Str.Append( "$Val`r`n" ) } $Result = $Str.ToString() } Measure-Command { test } 

実行結果:40,000行-1.8秒。

foreachをforに置き換えたり、内部変数$ testを捨てたりするなどのさらなる改善により、速度が大幅に向上することはありませんでした。

簡単に:

多数の行を効率的に処理するには、System.Text.StringBuilderオブジェクトを使用します。 コンストラクター呼び出し:

 $SomeString = New-Object System.Text.StringBuilder 

文字列に変換:

 $Result = $Str.ToString() 

StringBuilderの説明 (全体の秘密は、メモリマネージャのより効率的な作業にあります)。

Source: https://habr.com/ru/post/J273619/


All Articles