0

I created function to run script of "Power Shell script". I use Pipeline and Runspace ro run script (ex: power shell get-service) and run 1.000.000 times script “get-service” I see: - when run 1 script (1 pipeline and 1 runspace) then ram of application is about 300MB, when run complete, ram is about 70MB - ## Heading ##when run 2,3, 4 script (with 2,3,4 pipeline and 2,3,..) then ram of application is so hight, it is leaked memory, ram is about 1GB,.. and >2gb. I see problem from this position: When event pipelineExecutor_OnDataReady process, ram is up when call this function: ConvertToDataTable()

DataTable dtTable
    private void ConvertToDataTable(PSObject psObject, String host)
    {
    DataRow dr = dtTable.Rows.Add();
    foreach (PSPropertyInfo item in psObject.Properties)
    {                  
    string strvalue = string.Empty;
                   if (item.TypeNameOfValue != "System.Runtime.InteropServices.SafeHandle")
                   if (item.Value != null)
                   {                   
                        if (item.Value.GetType().FullName == "System.ServiceProcess.ServiceController[]")
                        {
                            ServiceController[] sController = (ServiceController[])item.Value;
                            foreach (ServiceController sCtrler in sController)
                            {
                                if (sCtrler.MachineName != ".")
                                strvalue += sCtrler.ServiceName + ", ";
                            }
                            if (strvalue.Length > 2)
                            strvalue = strvalue.Remove(strvalue.Length - 2);
                            `enter code here`strvalue = "{ " + strvalue + " }";
                        }
                        if (item.Value.GetType().BaseType.FullName == "System.Array")
                        {
                            var result = ((System.Collections.IEnumerable)item.Value).ToString();
                            strvalue = string.Join(", ", result);
                            if (!string.IsNullOrEmpty(strvalue))
                                strvalue = "{ " + strvalue + " }";
                        }
                        else
                            strvalue = item.Value.ToString();
                        if (selectedColsList.Contains(item.Name))                       
                                dr[item.Name] = strvalue;                                           
                    }
                }                           
          }
4 pipeline run 4 script with each script will run script 1000.000 times get-service and result of script from psoject will add into table, each table 100.000. I see when access to property of psoject then ram is up, if comment call ConvertToDataTable()function, ram is ok.
Please help me.
thanks
Hoang (hoang.cntt@gmail.com)
ArK
  • 20,698
  • 67
  • 109
  • 136

1 Answers1

0

One issue I see is the way you're creating the list of service names:

ServiceController[] sController = (ServiceController[])item.Value;
foreach (ServiceController sCtrler in sController)
{
    if (sCtrler.MachineName != ".")
        strvalue += sCtrler.ServiceName + ", ";
}
if (strvalue.Length > 2)
    strvalue = strvalue.Remove(strvalue.Length - 2);
strvalue = "{ " + strvalue + " }";

Each time you concatenate a service name to strvalue you are creating another intermediate string for the garbage collector to have to clean up. Ordinarily this might not be a big deal, but since you're running this code millions of times that can certainly add up. One alternative is to use a StringBuilder instead:

ServiceController[] sController = (ServiceController[])item.Value;

if (sController.Length < 1)
    strvalue = string.Empty;
else
{
    StringBuilder serviceNamesBuilder = new StringBuilder();
    ServiceController sCtrler = sController[0];

    if (sCtrler.MachineName != ".")
        serviceNamesBuilder.Append(sCtrler.ServiceName);
    for (int i = 1; i < sController.Length; i++)
    {
        sCtrler = sController[i];

        if (sCtrler.MachineName != ".")
            StringBuilder.Append(", ").Append(sCtrler.ServiceName);
    }

    strvalue = serviceNamesBuilder.ToString();
}

Also, I see that most of your loop involves building the value for strvalue, yet at the end you're potentially throwing that work away. I would restructure your loop like this to avoid computing a value that doesn't get used:

foreach (PSPropertyInfo item in psObject.Properties)
{
    if (item.TypeNameOfValue != "System.Runtime.InteropServices.SafeHandle"
        && item.Value != null
        && selectedColsList.Contains(item.Name)
    )
    {
        string strvalue;

        // Build value of strvalue...

        dr[item.Name] = strvalue;
    }
}
Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68