启动 - 睡眠内存泄漏(或导致PowerShell内存泄漏)?

时间:2015-06-05 16:23:26

标签: powershell

此问题是https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/365ca396-400d-4401-bd7f-05d5d6c22cc8/powershells-startsleep-causes-memory-growth?forum=winserverpowershell

的转贴

我没有在那里得到一个有效的答案,所以试试这个论坛是否有帮助。这阻碍了我的工作。

这是我的两个powershell脚本。第一个是创建事件源,第二个是使用4个线程生成事件。在每个线程中使用Start-Sleep来控制事件生成速率。如果我删除了Start-Sleep,那么powershell内存使用量是不变的,否则它会快速增长,直到使用所有系统内存并且系统变得非常慢。

这是一个已知问题吗?任何解决方法?感谢任何线索。

# use this script to create channel and source if they does not exist.

$logName = "TestLog"
$sourceName = "TestSource"

New-EventLog -LogName $logName -Source $sourceName

# maximumSize's max is 4G.
Limit-EventLog -LogName $logName -OverflowAction OverWriteOlder -RetentionDays 30 -MaximumSize 3080000KB

事件生成脚本:

# use this script to generate events in TestLog channel.

Param(
  [int]$sleepIntervalInMilliSeconds = 0
)

$eventGenScript = {
  $logName = "TestLog"
  $sourceName = "TestSource"

  while($true) {
    Write-EventLog -LogName $logName -Source $sourceName -Message "perfLog" -EventId 0 -EntryType information
    Start-Sleep -ms $sleepIntervalInMilliSeconds
  }
}

$threadCount = 4

for($i=0; $i -lt $threadCount; $i++)
{
  Start-Job $eventGenScript  
}

read-host "type a key to exit. You need to wait for some time for threads to exit."

1 个答案:

答案 0 :(得分:4)

Start-Sleep没有内存泄漏,你用无效的参数(-ms)调用它,并且作业的进程内存充满了错误消息,因为你一直在调用无限循环中的(无效)语句。

演示:

PS C:\> Start-Sleep -ms 100
Start-Sleep : A parameter cannot be found that matches parameter name 'ms'.
At line:1 char:13
+ Start-Sleep -ms 100
+             ~~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Sleep], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.StartSleepCommand

此外,您在scriptblock之外定义$sleepIntervalInMilliSeconds,但尝试在scriptblock中使用它,这将无效,因为该变量在scriptblock的范围内未定义。这就是为什么你的问题仍然存在,尽管你在微软论坛上得到了正确的建议。

PS C:\> $ms = 100
PS C:\> $job = Start-Job -ScriptBlock { Start-Sleep -Milliseconds $ms }
PS C:\> $job | Wait-Job | Receive-Job
Cannot validate argument on parameter 'Milliseconds'. The argument is null,
empty, or an element of the argument collection contains a null value.
Supply a collection that does not contain any null values and then try the
command again.
    + CategoryInfo          : InvalidData: (:) [Start-Sleep], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartSleepCommand
    + PSComputerName        : localhost

您有三种方法可以解决这个问题:

  • 在脚本块中定义变量:

    PS C:\> $job = Start-Job -ScriptBlock {
    >> $ms = 100
    >> $ms
    >> Start-Sleep -Milliseconds $ms
    >> }
    >>
    PS C:\> $job | Wait-Job | Receive-Job
    100
  • 使用using scope modifier获取本地变量:

    PS C:\> $ms = 100
    PS C:\> $job = Start-Job -ScriptBlock {
    >> $using:ms
    >> Start-Sleep -Milliseconds $using:ms
    >> }
    >>
    PS C:\> $job | Wait-Job | Receive-Job
    100
  • 将变量作为参数传递给scriptblock:

    PS C:\> $ms = 100
    PS C:\> $job = Start-Job -ScriptBlock {
    >> param($ms)
    >> $ms
    >> Start-Sleep -Milliseconds $ms
    >> } -ArgumentList $ms
    >>
    PS C:\> $job| Wait-Job | Receive-Job
    100

底线:替换

Start-Sleep -ms $sleepIntervalInMilliSeconds

Start-Sleep -Milliseconds $using:sleepIntervalInMilliSeconds

问题就会消失。