2016-11-02 42 views
0

我有一個PowerShell script,它讀取一個大的CSV文件(4GB +),找到某些行,然後將行寫入其他文件。PowerShell完成後清空內存

我注意到,當它到達「回顯」$ datafile文件中的處理$ datacounter總行數「」腳本的最後一行時,它直到5-10分鐘後才真正完成。

這段時間它在做什麼?當它結束時,內存使用量顯着下降。有沒有辦法強制它在腳本結尾處清除內存?

Screenshot of Memory Usage

Screenshot of script timestamps

這裏是我的參考腳本的最終版本。



    # Get the filename 
    $datafile = Read-Host "Filename" 
    $dayofweek = Read-Host "Day of week (IE 1 = Monday, 2 = Tuesday..)" 
    $campaignWriters = @{} 


    # Create campaign ID hash table 
    $campaignByID = @{} 
    foreach($c in (Import-Csv 'campaigns.txt' -Delimiter '|')) { 
     foreach($id in ($c.CampaignID -split ' ')) { 
      $campaignByID[$id] = $c.CampaignName 
     } 

     foreach($cname in ($c.CampaignName)) { 
      $writer = $campaignWriters[$cname] = New-Object IO.StreamWriter($dayofweek + $cname + '_filtered.txt') 
      if($dayofweek -eq 1) { 
       $writer.WriteLine("ID1|ID2|ID3|ID4|ID5|ID6|Time|Time-UTC-Sec") 
      } 
     } 
    } 

    # Display the campaigns 
    $campaignByID.GetEnumerator() | Sort-Object Value 

    # Read in data file 
    $encoding = [Text.Encoding]::GetEncoding('iso-8859-1') 
    $datareader = New-Object IO.StreamReader($datafile, $encoding) 
    $datacounter = 0 

    echo "Starting.." 
    get-date -Format g 

    while (!$datareader.EndOfStream) { 
     $data = $datareader.ReadLine().Split('þ') 

     # Find the Campaign in the hashtable 
     $campaignName = $campaignByID[$data[3]] 
     if($campaignName) { 
      $writer = $campaignWriters[$campaignName] 
      # If a campaign name was returned from the hash, add the line using that campaign's writer 
      $writer.WriteLine(($data[20,3,5,8,12,14,0,19] -join '|')) 
     } 
     $datacounter++; 
    } 

    $datareader.Close() 
    foreach ($writer in $campaignWriters.Values) { 
     $writer.Close() 
    } 

    echo "Done!" 
    get-date -Format g 
    echo "Processed $datacounter total lines in the $datafile file" 

+0

該腳本直到最後一行完成才真正完成。使用 「done:$(get-date -Format g)」來查看它何時發生。 – Jimbo

回答

0

它可能會或可能無法正常工作,但你可以嘗試告訴運行垃圾收集:

[System.GC]::Collect() 

您不必在它精細的控制,雖然,它可能有助於Remove-Variable或者在運行之前將變量設置爲$null,以便不再引用數據。

0

我假設campaigns.txt是您所指的多千兆字節文件。如果是其他文件,這可能沒有多大意義。

如果是這樣,調用import-csv內括號,然後使用foreach語句來遍歷它們是什麼推動你的內存使用如此之高。更好的選擇是使用PowerShell管道從文件中流式傳輸記錄,而不需要同時將所有記錄保存在內存中。您可以通過改變foreach statment成ForEach-Object cmdlet的實現這一點:

Import-Csv 'campaigns.txt' -Delimiter '|' | ForEach-Object { 
     foreach($id in ($_.CampaignID -split ' ')) { 
      $campaignByID[$id] = $_.CampaignName 
     } 
    } 

的.NET垃圾收集器進行了優化,其中大部分對象都是短命的案件。因此,這種變化應該會導致性能顯着增加,並且最終會縮短停機時間。

我建議針對強制垃圾回收與[System.GC]::Collect(),垃圾收集器知道什麼時候應該運行。原因很複雜,如果你真的想知道細節爲什麼這是真的,Maoni's blog有關於.NET環境中的垃圾收集的豐富的細節。

+0

感謝有關垃圾回收的信息。多GB文件實際上是由StreamReader讀取的'$ datafile'。 'campaigns.txt'文件非常小,只有10行。 – Esuriency