【问题标题】:Any idea why this simple program (creating powershell session) taking so much memory (~150 MB)?知道为什么这个简单的程序(创建 powershell 会话)占用这么多内存(~150 MB)吗?
【发布时间】:2011-11-11 06:00:13
【问题描述】:

我对 powershell 编程相当陌生。我正在创建远程会话以编程方式执行一些命令。但是它消耗了很多内存(大约 150 到 200 MB)。并且更多的会话,它的更多内存。

你能帮我解决这个问题吗?

  1. 罪魁祸首是什么?
  2. 我该如何解决?

观察: 1. 执行 CreateRunSpace 命令后,消耗约 3MB。


有人在创建运行空间时遇到了同样的问题:

http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/69ccce9d-4696-4886-a5d0-5d2d2e1e4e6d

“可能的 PowerShell 运行空间句柄泄漏”

仍在调查以找到答案...

删除 pssession 使运行空间释放句柄并修复内存泄漏。它现在在 ~30 到 40MB 之间切换。


谢谢!

(仅供参考 - 引用 System.Management.Automation.dll)

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation.Runspaces;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            int success = 0;
            int fails = 0;
            for (int i = 0; i < 50; i++)
            {
                Runspace rs = RunspaceFactory.CreateRunspace();
                //After this the memory will be incremented by ~3Mb in taskmanager
                rs.Open();
                using (Pipeline pl = rs.CreatePipeline())
                {
                    Command cmd = new Command("new-pssession");
                    pl.Commands.Add(cmd);
                    var retval = pl.Invoke();
                    if (retval.Count > 0)
                    {
                        success++;
                    }
                    else
                    {
                        fails++;
                    }
                    pl.Stop();
                }
                rs.Close();
                rs = null;
            }
            GC.Collect();

        }

    }
}

【问题讨论】:

标签: c# .net powershell c#-3.0 powershell-2.0


【解决方案1】:

看起来像从运行空间中删除-pssession 释放了内存句柄并修复了泄漏。现在它占用了大约 35MB。

int success = 0;
int fails = 0;
for (int i = 0; i < 50; i++)
{
    Runspace rs = RunspaceFactory.CreateRunspace();
    rs.Open();
    using (Pipeline pl = rs.CreatePipeline())
    {
        Command cmd = new Command("new-pssession");
        pl.Commands.Add(cmd);
        var retval = pl.Invoke();
        if (retval.Count > 0)
        {
            success++;
            PSSession Session = (PSSession)retval[0].BaseObject;
            using (Pipeline pl2 = rs.CreatePipeline())
            {
                Command cmd2 = new Command("remove-pssession");
                cmd2.Parameters.Add("Id", Session.Id);
                pl2.Commands.Add(cmd2);
                var retval2 = pl2.Invoke();
                pl2.Stop();
            }
        }
        else
        {
            fails++;
        }
        pl.Stop();
    }
    rs.Close();
    rs = null;
}

【讨论】:

    【解决方案2】:

    Runspace 对象是一次性的,如果你编码是一样的吗:

    using (Runspace rs = RunspaceFactory.CreateRunspace())
    {
    }
    

    【讨论】:

    • 如果类提供 Close 方法,建议调用 Close 而不是 Dispose。两种方法都做同样的事情,特别是如果这是一个框架类。因此,他的代码很好。
    • 是的,没有影响。一样的。
    • @AMissico 实际上,Dispose 模式必须确保所有内容都被清理干净,因此如果类已正确实现,则不必调用 Close()
    • @IgorBrejc - 我发现的几乎所有 Microsoft 文档都建议在调用 Dispose 之前调用 Close。 Dispose 模式的任何实现都将在处理之前调用 Close。在 Microsoft .NET 源代码中搜索大量示例。
    • @AMissico 正是我的观点 :)。如果 Dispose 模式涵盖了 Close(),为什么还需要显式调用它?它实际上破坏了 using() 块的用处,因为您需要在其中嵌入一个额外的 try-final 块以保证调用 Close()。有什么好处?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多