2015-11-16 95 views
0

我創建了運行「Power Shell腳本」腳本的函數。 我使用Pipeline和Runspace ro run腳本(例如:power shell get-service)並運行1.000.000次腳本「get-service」 我看到: - 當運行1腳本(1個管道和1個運行空間)時,應用程序是大約300MB,運行完成後,內存大約70MB - ##標題##運行2,3,4腳本(與2,3,4管道和2,3,..)然後應用程序的ram是如此高度,它是泄露的內存,RAM約1GB,..和> 2GB。 我看到的問題,從這個位置:當事件pipelineExecutor_OnDataReady過程中,RAM高達調用該函數時:ConvertToDataTable()我創建了運行「Power Shell腳本」腳本的函數

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 ([email protected]) 

回答

0

一個問題我看到的是你要創建的服務名稱的列表方式:

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 + " }"; 

每次將服務名稱連接到strvalue時,您正在爲垃圾收集器必須清理創建另一箇中間string。通常這可能不是什麼大問題,但是因爲你運行的代碼數百萬次,肯定會增加。一種選擇是使用StringBuilder來代替:

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(); 
} 

另外,我看到大部分的循環包括建設價值strvalue,但在最後你可能拋出的工作了。我會像這樣重構你的循環,以避免計算一個不被使用的值:

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; 
    } 
}