PowerShell 5.1 中的性能问题

performance issue in PowerShell 5.1

我有一个读取和解析文本文件的 powershell 脚本。文件被读入内存,然后逐行处理。

当我从 Powershell 4.0 切换到 5.1 时,脚本变得慢了大约 10 倍(60 秒而不是 6 秒)。 有谁知道如何让脚本 运行 更快?

#------------------------------------------------------------------------
# Function GetNextLine.
# Read next text line from input text array into variables.
# Parameter:
#    $inTextArr[]: (in)    Input text array
#    $linenr     : (inout) line number, will be increased
#    $line       : (out)   read text line
#    $line2      : (out)   read text line without leading and trailing spaces
#    $s1         : (out)   first word read in text line
#------------------------------------------------------------------------
function GetNextLine {
   param (
       [ref]$inTextArr
      ,[ref]$linenr
      ,[ref]$line
      ,[ref]$line2
      ,[ref]$s1
   ) 
   $linenr.value++
   $line.value = $inTextArr.value[$linenr.value-1]
   $line2.value= $line.value.trim()
   $s1.value   = $line2.value.split(" ")[0]
} # function GetNextLine
#------------------------------------------------------------------------

#------------------------------------------------------------------------
# Function ParseMifFile.
# Parse input text array.
#------------------------------------------------------------------------
function ParseMifFile { 
   param( 
      [ref]$inTextArr
   )

   # Initialize output parameters and variables.
   [int]$linenr  = 0
   [string]$line = ""
   [string]$line2= ""
   [string]$s1   = ""
   
   # (Extract. The orginal script has lots of GetNextLine calls.)
   GetNextLine -inTextArr ([ref]$inTextArr.value) -linenr ([ref]$linenr) -line ([ref]$line) -line2 ([ref]$line2) -s1 ([ref]$s1)
   while ($line -cne "# End of MIFFile") {
      GetNextLine -inTextArr ([ref]$inTextArr.value) -linenr ([ref]$linenr) -line ([ref]$line) -line2 ([ref]$line2) -s1 ([ref]$s1)     
   }
} # function ParseMifFile
#------------------------------------------------------------------------

# Prepare a large text array for performance test below (just for test purpose, instead of reading in the input file).
$inTextArr= @()
for ($i= 1; $i -lt 50000; $i++) {
   $inTextArr= $inTextArr + "This is a line from the input file"
}
$inTextArr= $inTextArr + "# End of MIFFile"

# Performance test of function ParseMifFile.
measure-command {
   ParseMifFile -inTextArr ([ref]$inTextArr) 
   # Very slow in Powershell 5.1.17763.2803 (60 sec) compared to Powershell 4.0 (6 sec) 
}

不确定为什么在 5.1 中速度变慢,但是您将整个内容传递给每个 nextline 函数调用。

“有谁知道如何让脚本 运行 更快?”

时间如何?它应该获取您的文件内容并将每一行传递到一个类似的对象中。

$MyContentArray = Get-Content -Path "[C:\My\FilePath]" | ForEach-Object {
    [PSCustomObject]@{
        liner = $i++
        line = $_
        line2 = $_.trim()
        s1 = ($_.trim()).split(" ")[0]
    }
}

Get-Content

PSCustomObject

在我看来,使用引用参数将文本数组传递给函数会花费很多时间。

作为替代方案,我按照 tanstaafl 之前的回答中的建议创建了一个自定义对象,其中包含有关当前读取的文件行的所有信息。 该程序快得多(1.5 秒)而不是 60 秒。

function GetNextLine {
   param (
      [PSCustomObject]$linePtrO     
   ) 
   $linePtrO.linenr++
   $linePtrO.line = $linePtrO.inTextArr[$linePtrO.linenr-1]
   $linePtrO.line2= $linePtrO.line.trim()
   $linePtrO.s1   = $linePtrO.line2.split(" ")[0]
} # function GetNextLine

function ParseMifFile {
   param (
      [string]$inFileNameStr
   )
   $linePtrO = [PSCustomObject] @{
        inTextArr = get-content -path $inFileNameStr -encoding utf8
        linenr    = 0
        line      = ""
        line2     = ""
        s1        = ""
   }     
   # (Extract. The orginal script has lots of GetNextLine calls.)
   GetNextLine -linePtrO $linePtrO

   while ($linePtrO.line -cne "# End of MIFFile") {
      GetNextLine -linePtrO $linePtrO    
   }
} # function ParseMifFile

$fileNameStr= "C:\mypath\myfile"
ParseMifFile -inFileNameStr $fileNameStr