Performance Powershell:较小的文件在没有“Out file”的情况下写入所需的时间延长30倍

Performance Powershell:较小的文件在没有“Out file”的情况下写入所需的时间延长30倍,performance,powershell,file-writing,Performance,Powershell,File Writing,我得到一个文件的内容,只保留与正则表达式或空行匹配的行。但是写结果,比如说写更少的数据,需要花费很多时间。。。 以下是我添加了几行用于调试/测量的代码: $original = Get-Content "$localDir\$ldif_file" (Measure-Command -Expression { $original | Out-File "$localDir\Original-$ldif_file" }).TotalSeconds $lines = ($original | Meas

我得到一个文件的内容,只保留与正则表达式或空行匹配的行。但是写结果,比如说写更少的数据,需要花费很多时间。。。 以下是我添加了几行用于调试/测量的代码:

$original = Get-Content "$localDir\$ldif_file"
(Measure-Command -Expression { $original | Out-File "$localDir\Original-$ldif_file" }).TotalSeconds
$lines = ($original | Measure-Object -Line).Lines
"lines of `$original = $lines"

# Just keep lines of interest:
$stripped = $original | select-string -pattern '^custom[A-Z]','^$' -CaseSensitive
$lines = ($stripped | Measure-Object -Line).Lines
"lines of `$stripped = $lines"
(Measure-Command -Expression { $stripped | Out-File "$localDir\Stripped-$ldif_file" }).TotalSeconds

"done"
问题:较小的$stripped数据需要342秒才能写入一个文件,大约比$original数据长30倍!见下面的输出:

11.5371677
lines of $original = 188715
lines of $stripped = 126404
342.6769547
done
为什么$stripped的Out文件比$original的慢得多? 如何改进


谢谢

你真的在比较苹果和桔子

$original包含189K个字符串,但$stripped包含126K个MatchInfo对象,这些对象必须在管道中逐个转换为字符串

改用-cmatch运算符保留原始字符串输入值,您会发现将其输出到文件的速度要快得多:

$original = Get-Content "$localDir\$ldif_file"
(Measure-Command -Expression { $original | Out-File "$localDir\Original-$ldif_file" }).TotalSeconds
$lines = ($original | Measure-Object -Line).Lines
"lines of `$original = $lines"

# Just keep lines of interest:
$stripped = $original |Where-Object {$_ -cmatch '^custom[A-Z]' -or $_ -like ''}
$lines = ($stripped | Measure-Object -Line).Lines
"lines of `$stripped = $lines"
(Measure-Command -Expression { $stripped | Out-File "$localDir\Stripped-$ldif_file" }).TotalSeconds

"done"

你真的在比较苹果和桔子

$original包含189K个字符串,但$stripped包含126K个MatchInfo对象,这些对象必须在管道中逐个转换为字符串

改用-cmatch运算符保留原始字符串输入值,您会发现将其输出到文件的速度要快得多:

$original = Get-Content "$localDir\$ldif_file"
(Measure-Command -Expression { $original | Out-File "$localDir\Original-$ldif_file" }).TotalSeconds
$lines = ($original | Measure-Object -Line).Lines
"lines of `$original = $lines"

# Just keep lines of interest:
$stripped = $original |Where-Object {$_ -cmatch '^custom[A-Z]' -or $_ -like ''}
$lines = ($stripped | Measure-Object -Line).Lines
"lines of `$stripped = $lines"
(Measure-Command -Expression { $stripped | Out-File "$localDir\Stripped-$ldif_file" }).TotalSeconds

"done"
补充:

在PowerShell 7中,现在支持-Raw开关,它只输出匹配行的字符串,这将大大加快命令的执行速度

在Windows PowerShell中,效率较低的是,您可以将Select String调用括在…行中,以仅将行作为字符串获取

还请注意,如果直接向选择字符串传递一个文件路径,使其读取文件本身,而不是通过Get Content管道传输单独的行,则选择字符串的速度会快得多

通常,对于编写已经是字符串的对象,与输出文件相比,设置内容是更好、更快的选择

有关背景信息,请参阅;有关性能比较,请参阅的底部部分

字符编码警告请参见背景:

在Windows PowerShell中,将内容默认设置为ANSI编码,而Out文件默认设置为Unicode UTF-16LE;根据需要使用-编码。 幸运的是,PowerShell[Core]6+使用了一致的默认值,即不带BOM的UTF-8。 通过管道传递集合可能很慢;对于已完全存储在内存中的集合,将它们作为一个整体传递(而不是作为参数传递)要快得多-假设目标cmdlet支持-Set Content的-Value参数

总而言之:

# *PowerShell 7*: Use -Raw to directly get the lines as string.
$stripped = $original | 
  Select-String -Raw -Pattern '^custom[A-Z]','^$' -CaseSensitive

# *Windows PowerShell*: Use (...).Line to get the lines as strings.
$stripped = ($original | 
  Select-String -Pattern '^custom[A-Z]','^$' -CaseSensitive).Line

$lines = $stripped.Count # Simply count the array elements == number of lines.
"lines of `$stripped = $lines"

(Measure-Command -Expression { 
  Set-Content "$localDir\Stripped-$ldif_file" -Value $stripped
}).TotalSeconds
补充:

在PowerShell 7中,现在支持-Raw开关,它只输出匹配行的字符串,这将大大加快命令的执行速度

在Windows PowerShell中,效率较低的是,您可以将Select String调用括在…行中,以仅将行作为字符串获取

还请注意,如果直接向选择字符串传递一个文件路径,使其读取文件本身,而不是通过Get Content管道传输单独的行,则选择字符串的速度会快得多

通常,对于编写已经是字符串的对象,与输出文件相比,设置内容是更好、更快的选择

有关背景信息,请参阅;有关性能比较,请参阅的底部部分

字符编码警告请参见背景:

在Windows PowerShell中,将内容默认设置为ANSI编码,而Out文件默认设置为Unicode UTF-16LE;根据需要使用-编码。 幸运的是,PowerShell[Core]6+使用了一致的默认值,即不带BOM的UTF-8。 通过管道传递集合可能很慢;对于已完全存储在内存中的集合,将它们作为一个整体传递(而不是作为参数传递)要快得多-假设目标cmdlet支持-Set Content的-Value参数

总而言之:

# *PowerShell 7*: Use -Raw to directly get the lines as string.
$stripped = $original | 
  Select-String -Raw -Pattern '^custom[A-Z]','^$' -CaseSensitive

# *Windows PowerShell*: Use (...).Line to get the lines as strings.
$stripped = ($original | 
  Select-String -Pattern '^custom[A-Z]','^$' -CaseSensitive).Line

$lines = $stripped.Count # Simply count the array elements == number of lines.
"lines of `$stripped = $lines"

(Measure-Command -Expression { 
  Set-Content "$localDir\Stripped-$ldif_file" -Value $stripped
}).TotalSeconds

谢谢你完整的回答。我现在需要坚持使用Windows Powershell,但是根据您的建议。现在就行并设置内容文件在一秒钟内写入!谢谢你完整的回答。我现在需要坚持使用Windows Powershell,但是根据您的建议。现在就行并设置内容文件在一秒钟内写入!谢谢,文件写入速度确实快得多,但在这种情况下,模式匹配需要更长的时间。总体上没有什么真正的改进。谢谢,文件编写确实快得多,但在这种情况下,模式匹配需要更长的时间。总的来说没有真正的改善。