Powershell工作记忆消耗问题

时间:2015-03-30 16:02:27

标签: powershell memory ffmpeg start-job

我一直在努力解决这个问题一周,并且已经用尽了我在网上找到的所有方法和选项。我希望有人能够帮助我解决这个问题。

我正在使用powershell启动8个作业,每个作业运行FFmpeg以将7分钟文件流式传输到远程RTMP服务器。这是从磁盘上的文件中提取的,每个作业使用不同的文件。该命令位于do while循环中,因此它会不断地进行重新调用。

这导致我启动作业的shell积累了大量内存,消耗了所有可能的内存。在24小时内,它消耗了32 GB的服务器中的30个。

这是我的启动代码,任何帮助都将不胜感激。

start-job -Name v6 -scriptblock {
do { $d = $true; $f = Invoke-Expression -Command "ffmpeg -re -i `"C:\Shares\Matthew\180p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"; $f = $null }
while ($d = $true)

}

我已经尝试接收作业并将其管道输出为null,我尝试在启动do while循环之前将$ f设置为$ null,以及我在网上找到的其他一些东西但无济于事。谢谢大家的时间!

2 个答案:

答案 0 :(得分:3)

迟到总比我想的要好。在Powershell作业中运行ffmpeg时,我遇到了同样的大量内存消耗问题。问题的核心是Powershell作业将任何/所有输出存储到内存中,ffmpeg非常乐意将输出记录到标准输出和标准错误流。

我的解决方案是将参数“-loglevel quiet”添加到ffmpeg。或者,您可以将标准流和错误流重定向到null(仅仅重定向标准流是不够的)。有关如何重定向标准流的更多信息,请参阅以下问题:Redirection of standard and error output appending to the same log-file

答案 1 :(得分:2)

有许多方法可以调用PowerShell脚本或表达式。

我最喜欢的一个是使用RunspacePool。在RunspacePool中,每个任务都以新的运行空间启动。任务完成后,将丢弃运行空间。这应该使内存消耗保持相当稳定。这不是解决问题的最简单方法,但这是一个可能适合您的裸体示例。

$Throttle = 10 # Maximum jobs that can run simultaneously in a runpool
$maxjobs = 8 # Maximum jobs that will run simultaneously
[System.Collections.ArrayList]$jobs = @()
$script:currentjobs = 0
$jobindex = 0
$jobaction = "ffmpeg -re -i `"C:\Shares\Matthew\180p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"

$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspace = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspace.Open()


function QueueJob{
    param($jobindex)
    $job = "" | Select-Object JobID,Script,Errors,PS,Runspace,Handle
    $job.JobID = $jobindex
    $job.Script = $jobaction
    $job.PS = [System.Management.Automation.PowerShell]::create()
    $job.PS.RunspacePool = $runspace
    [void]$job.PS.AddScript($job.Script)
    $job.Runspace = $job.PS.BeginInvoke()
    $job.Handle = $job.Runspace.AsyncWaitHandle
    Write-Host "----------------- Starting Job: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Blue
    $jobs.add($job)
    $script:currentjobs++
}

Function ServiceJobs{
    foreach($job in $Jobs){
        If ($job.Runspace.isCompleted) {
            $result = $job.PS.EndInvoke($job.Runspace)
            $job.PS.dispose()
            $job.Runspace = $null
            $job.PS = $null
            $script:currentjobs--
            Write-Host "----------------- Job Completed: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Yellow
            Write-Host $result
            $Jobs.Remove($job)
            return
        }
    }
}

while ($true) {
    While ($script:currentjobs -le $maxjobs){
        QueueJob $jobindex
        $jobindex++
    }
    ServiceJobs
    Start-Sleep 1
}

$runspace.Close()
[gc]::Collect() 

它使用无限循环而没有正确终止,并且缺少任何类型的错误检查,但希望它足以证明该技术。