代码之家  ›  专栏  ›  技术社区  ›  markdemich

PowerShell使用大量内存解压缩GZip管道

  •  1
  • markdemich  · 技术社区  · 8 年前

    我正在编写一个powershell Cmdlet,以接受对gzipped文件的文件引用列表,并解压缩它们并将它们的文本行放到管道上。我有一些功能,但它正在使用大量的内存。有趣的是,完成后,如果我在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()
            }
    
        }
    
    }
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Χpẘ    8 年前

    OP中的问题似乎是:“我做错了什么?”。

    我不认为有什么必然的错误。当OP状态时,GC发生后,内存恢复正常。除非脚本或系统其他部分出现性能问题,否则我没有理由说有问题。

    OP不够具体,无法知道:1.内存使用是否与缓冲区大小有关?2.或者是否与文件大小有关?若文件大小在65K左右,那个么很难确定。

    假设内存使用与缓冲区的大小有关,那么当查看副本时,内存为什么是缓冲区大小的几倍就变得很清楚了。1.有一份副本是由于 GetString .2.另一项因 -split 3.另一个原因是 Write-Output 属于 $temp .4根据 System.IO.Compression.GzipStream System.IO.FileStream 它们可以各自具有未知大小的缓冲区。所以这至少是4X 65K。