Утечки памяти в C # на хостинге Powershell - PullRequest
2 голосов
/ 14 марта 2019

У меня есть простое приложение, которое создает пространство выполнения Powershell:

        var iis = InitialSessionState.CreateDefault();
        iis.ExecutionPolicy = ExecutionPolicy.Unrestricted;
        iis.LanguageMode = PSLanguageMode.FullLanguage;
        iis.ThreadOptions = PSThreadOptions.UseNewThread;
        iis.DisableFormatUpdates = true;

        m_Settings = new PSInvocationSettings
        {
            Host = new PSHostProxy(new PSUIStub()),
        };

        m_RunspacePool = RunspaceFactory.CreateRunspacePool(iis);
        m_RunspacePool.CleanupInterval = new TimeSpan(0, 0, 10);
        m_RunspacePool.SetMaxRunspaces(1);
        m_RunspacePool.SetMinRunspaces(1);
        m_RunspacePool.Open();

А затем использует его для выполнения нескольких скриптов PowerShell. Каждое RUN вызывается внешним событием (запускается в другом потоке) и происходит обычно через 20-50 секунд после предыдущего RUN:

RUN:
{
  foreach(var scriptName in scripts)
  {
    var ps = PowerShell.Create();
    ps.RunspacePool = m_RunspacePool;
    var input = new PSDataCollection<string>();

    ps.AddCommand(Path.Combine(scriptPath, scriptName));
    ps.AddArgument(args);

    // Call
    ps.Invoke(input, m_Output, m_Settings);
    ...
    m_Output.Clear();
    input.Clear();
    input.Dispose();

    ps.Dispose();
    ps = null;
  }
}

И использование памяти продолжает расти во время выполнения, хотя сценарии всегда одинаковы, и даже их результаты одинаковы. Каждый цикл создает связку (как и тысячи из них, но я полагаю, что число определяется длиной исполняемых скриптов ...) SessionStateCmdLetEntry, и они никогда не удаляются и не GCed из-за ссылки TimerCallback, созданной RunspacePoolInternal. Это может занять до 1 ГБ памяти в день ...

У кого-нибудь есть советы, что еще я должен распорядиться или очистить, чтобы не хранить SessionStateCmdLetEntries? Или какие-нибудь обходные пути для этого?

Мне просто нужен длительный процесс, который вызывает несколько сценариев Powershell и не потребляет память. Я также пытался не использовать RunSpacePool повторно и создавать новое Runspace для каждого RUN и даже для каждого сценария, но он это сделал совсем не помогает ...

Спасибо за любую помощь ...

1 Ответ

0 голосов
/ 22 марта 2019

Это показывает, что утечка вызвана не кодом C #, а сценарием PowerShell, выполняемым через это.Сценарий создает собственные экземпляры RunspacePool и PowerShell для выполнения определенного кода, что приводит к утечке памяти.

...