2016-11-02 4 views
0

Ich habe eine PowerShell script, die eine große CSV-Datei (4GB +) liest, bestimmte Zeilen findet, schreibt dann die Zeilen in andere Dateien.PowerShell Clearing-Speicher nach Abschluss

Ich merke, dass, wenn es zu "echo" Verarbeitete $ Datenzähler insgesamt Zeilen in der $ Datendatei-Datei "" die letzte Zeile des Skripts, es nicht wirklich bis 5 bis 10 Minuten später fertig ist.

Was macht es für diesen Zeitraum? Wenn dies abgeschlossen ist, sinkt die Speicherbelegung erheblich. Gibt es eine Möglichkeit, es am Ende des Skripts zum Löschen von Speicher zu zwingen?

Screenshot of Memory Usage

Screenshot of script timestamps

Hier ist die letzte Version von meinem Skript Referenz.



    # 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

Das Skript wird nicht wirklich ausgeführt, bis die letzte Zeile abgeschlossen ist. Verwenden Sie "done: $ (get-date -Format g)" zu sehen, wenn es genau passiert – Jimbo

Antwort

0

Es kann oder auch nicht, aber man kann versuchen, die Garbage Collection zu sagen auszuführen:

[System.GC]::Collect() 

Sie haben noch feinkörnige Kontrolle über es aber, und es kann zu Remove-Variable helfen oder setze Variablen für einige Dinge auf $null, bevor du sie ausführst, so dass es keine Verweise mehr auf die Daten gibt.

0

Ich nehme an, dass campaigns.txt die Multi-Gigabyte-Datei ist, auf die Sie sich beziehen. Wenn es die anderen Datei (en) ist, macht dies möglicherweise nicht so viel Sinn.

Wenn ja, rufen Sie import-csv die innere Klammer dann mit der foreach Anweisung, um durch sie zu durchlaufen ist, was Ihre Speichernutzung so hoch ist. Eine bessere Alternative wäre die Verwendung einer PowerShell-Pipeline, um Datensätze aus der Datei zu streamen, ohne sie alle gleichzeitig im Speicher zu behalten. Sie erreichen dies durch die foreach statment in ein ForEach-Object Cmdlets Wechsel:

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

.NET Garbage Collector ist Fälle optimiert, in denen die Mehrzahl der Objekte kurzlebig sind. Daher sollte diese Änderung zu einer spürbaren Leistungssteigerung sowie einer reduzierten Abbauzeit am Ende führen.

Ich rate gegen zwingen Garbage Collection mit [System.GC]::Collect(), der Müllsammler weiß am besten, wenn es laufen sollte. Die Gründe dafür sind komplex. Wenn Sie wirklich wissen möchten, warum dies der Fall ist, enthält Maoni's blog eine Fülle von Details zur Garbage Collection in der .NET-Umgebung.

+0

Danke für die Infos über Garbage Collection. Die Multi-GB-Datei ist eigentlich die '$ Datendatei ', die vom StreamReader gelesen wird. Die 'campaigns.txt' Datei ist sehr klein, nur wie 10 Zeilen. – Esuriency

Verwandte Themen