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]
}
}
在我看来,使用引用参数将文本数组传递给函数会花费很多时间。
作为替代方案,我按照 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
我有一个读取和解析文本文件的 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]
}
}
在我看来,使用引用参数将文本数组传递给函数会花费很多时间。
作为替代方案,我按照 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