我正在编写一个powershell Cmdlet来接受对gzip文件的文件引用列表,并将它们解压缩并将它们的文本行放在管道上。我有一些功能,但它使用了大量的内存。有趣的是,完成后,如果我在powershell提示符下运行[System.GC] :: Collect(),它将释放内存。我尝试在循环中运行它,但它影响了性能。有人能指出我做错了什么。我认为使用管道的一个好处是节省内存。即使我将它传递给单个文件引用,它也会使用比文件大小更多的内存。
这是我的代码。
<#
.SYNOPSIS
Accepts GZip files piped in and outputs decrompessed text to the pipe.
.DESCRIPTION
You can use this function to pipe a list of serveral gzipped files. They will then be decompress and concatenated
and the text will be written to the output where it can be piped to another function.
.PARAMETER PipedFile
A list of gzipped file references.
.EXAMPLE
Get-ChildItem "*.gz" | Decompress-Gzip
#>
Function Decompress-GZip {
Param(
[Parameter(ValueFromPipeline=$true)]
[System.IO.FileInfo]$PipedFile
)
Process {
If ( $PipedFile.Exists -eq $False) {
Write-Host "File $PipedFile does not exist. Skipping."
return
}
$BUFFER_SIZE = 65536
$infile = $PipedFile.FullName
$inputfile = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
$gzipStream = New-Object System.IO.Compression.GzipStream $inputfile, ([IO.Compression.CompressionMode]::Decompress)
try {
$buffer = New-Object byte[]($BUFFER_SIZE)
While (($read = $gzipstream.Read($buffer, 0, $BUFFER_SIZE)) -gt 0) {
$str = [System.Text.Encoding]::ASCII.GetString($buffer,0,$read)
$temp = $str -split "`r`n"
if ($temp.Length -gt 0) {
if ($lastLine) {
$temp[0] = $lastLine + $temp[0]
}
if ($temp.Length -gt 1) {
Write-Output $temp[0..($temp.Length-2)]
}
$lastLine = $temp[($temp.Length-1)]
}
}
} finally {
$gzipStream.Close()
$inputfile.Close()
}
}
}
答案 0 :(得分:1)
OP中的问题似乎是:“我做错了什么?”。
我认为没有任何错误。如OP所述,GC发生后内存恢复正常。除非在脚本内或在系统的其他部分内存在性能问题,否则我没有理由说出现问题。
OP的具体程度不足以了解:1。如果内存使用与缓冲区的大小有关? 2.或者它是否与文件大小有关?如果文件大小约为65K,则很难确定。
假设内存使用与缓冲区的大小有关,则可以清楚地了解为什么当查看副本时内存的大小是缓冲区大小的几倍。 1.由GetString
制作副本。 2.另一个由于-split
而产生。 3.另一个归因于Write-Output
的{{1}}。 4.根据$temp
和System.IO.Compression.GzipStream
的实现,他们每个人都可以拥有自己的未知大小的缓冲区。这至少是4X 65K。