Jump to content

Empfohlene Beiträge

Hallo Zusammen,

 

mit fehlt leider die Erfahrung um folgendes Script performanter zu machen. Leider finde ich auch nicht wirklich etwas im Netz dazu.

 

Generell liegt das Problem wahrscheinlich auch in der Größe der Log Datei, die durchsucht wird. Die Datei ist ca. 40GB groß.

In der Adressen.txt sind ca. 1000 E-Mail Adressen enthalten. Es muss geprüft werden, welche E-Mail Adresse in dem 40GB großen Dokument vorhanden ist.

Wenn es vorhanden ist, soll im Output-Dokument hinter der E-Mail ein "Ja" geschrieben werden.

Vielen Dank im Voraus!

 

Gruß Tim

$logFolder = "H:\logs.txt"
$adressen= Get-Content H:\Adressen.txt
$ergebnis = @()
    
foreach ($adr in $adressen){
    $suche =  Select-String -Path $logFolder -Pattern "\[\(\'from\'\,.*$adr.*\'\)\]" -List
    $aktiv= $false
    $adr
    if ($suche){
        $aktiv = $true 
    }

    if ($aktiv -eq $true){
        $ergebnis+=$adr + ";Ja"
    }
    else{
        $ergebnis+=$adr + ";Nein"
    }
}
$ergebnis |Out-File H:\output.txt

 

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Hallo und willkommen im Forum.

Z.B. alle Adressen in ein Arrary laden und diese Array dann zeilenweise gegen die Log-Datei prüfen.

Also eine Zeile aus LOG-Datei lesen und alle 1000 Adressen im Array gegen die Zeile prüfen.

So wird die Log-Datei nur 1x gelesen.

bearbeitet von zahni

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Das Problem ist hier glaube ich weniger, dass das schreiben der Datei bzw. des Arrays so lange dauert. Die Überprüfung von einer Zeile (1x E-Mail) aus der Adressen.txt auf die ganze mail.log dauert mehrere Minuten, wenn diese nicht gefunden wird und somit natürlich bis zum ende durchsucht wird.

Leider weiss ich nicht, wie man jeweils immer 1000 Adressen auf eine zeile überprüfen würde. Wäre das wirklich schneller?

vor 12 Minuten schrieb testperson:

Hi,

 

wo kommt denn das Log her? Lässt sich das evtl. direkt in etwas performanteres wie eine einfache Textdatei schreiben (z.B. SQL)?

 

Gruß

Jan

Leider nur die Möglichkeit in diesem Format :(

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Du hast doch oben das Beispiel.

Du packst die Log-Datei in einer foreach-Schleife und dort verschachtelt eine Foreach für das Array.

 

 

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Hab mal das ganze nachgestellt.

Bei etwas über 1000 Adressen und einer Log Datei mit knapp 190 MB.

Dein Script läuft ca. 49 min, da (wie schon angemerkt) die große Datei bei jeder Adresse aufgemacht wird.

 

$adressen = Get-Content H:\Adressen.txt
$ergebnis = @()

foreach($line in (Get-Content "H:\logs.txt")){
   if($adressen.contains($line)){
      #$line # Nur Ausgabe, kann direkt in Output Datei gespeichert werden, wenn Dupletten erlaubt sind
      $ergebnis += $line # Zwischenspeichern, wenn Dupletten erlaubt sind, kann das weggelassen werden, wenn in der Zeile davor das Ergebnis gespeichert wird.
   }
}

$ergebnis | Sort-Object -Unique | Out-File H:\output.txt # Ergebnis OHNE Dupletten speichern
#$ergebnis | Out-File H:\output.txt # Ergebnis MIT Dupletten speichern

Je nachdem, ob du Dupletten erlauben willst oder nicht kannst du entsprechende Elemente auskommentieren.

Das Script läuft auf den gleichen Dateien wie oben ca. 12 Min.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

1. Wurde ja schon angemerkt - das Suchen von 1000 Adressen in jeder einzelnen Zeile geht schneller als die Logdatei 1000 mal zu lesen :-)

2. Umstellen - dringend. .Net Streamreader - das Inet liefert Dir das HowTo dazu. Get-Content ist um Potenzen langsamer.

3. += ist böse. Besser ein .Net ArrayList (oder wie das heißt :-) ) verwenden, auch da liefert das Inet.

4. Pipes vermeiden - immer und überall. Pipes sind auch schnarch...

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Ein Dictionary ist in der Regel noch schneller als eine Array. Zumindest so meine Erfahrung, auch wenn sich diese hauptsächlich auf VB6 beschränkt und meine Erfahrung etwas angestaubt ist. Denke aber, das wird in .Net nicht anders sein. =)

EDIT: Habe mal schnell in einer meiner Sources geschaut weil es mir grad unlogisch war weil der dic ja ein Objekt ist und die Elemente selber auch Objekte. Das heisst meist ist Dictonary eigentlich schneller als eine Collection nicht eines Arrays. Der Geschwindigkeitsvorteil gegenüber einem Array resultiert dann, wenn du das "Exist" als Vergleichsoperator benutzt. Also die zu vergleichenden Strings als Key hinzufügst. Der Grund ist, dass der Vergleich auf C++ Ebene innerhalb des Dics abläuft und nicht in der höheren Programmiersprache selber wo der Vergleich sowas wie  If A = B then ... heisst.  Je nach Programmiersprache ist der Unterschied deutlich spürbar oder nur minimal. Bei VB war das jeweils ziemlich heftig bei grösseren Datenmengen.

 

Eine Umsetzung in C++ gibt für "stupide" Massenverarbeitung in der Regel auch ein Performance-gewinn, ist aber (deutlich) mühsamer zu programmieren. Zumindest wenn man es sich nicht gewohnt ist. Da die Anforderungen hier nicht besonders gross sind, wärs vielleicht ein Versuch wert.

 

Dann helfen natürlich die üblichen Hardware-Empfehlungen wie möglichst hohe Taktrate, je nach Sofware und Programmierung die Anzahl Kerne und insbesondere die IOPS und RAM. Vielleicht würde auch eine RAM-Disk helfen oder das komplette laden der Datei ins RAM bzw. in die Software oder eben das vorherige Aufarbeiten der Daten/import in eine DB oder oder oder  ;-)

Dazu müsste man aber mehr zu dieser Logdatei wissen. Aufbau usw. sonst ist das schwer zu beurteilen. Oft läufts auch einfach auf Try and Error raus. ;)

 

Schlussendlich sollte man in solchen Fällen möglichst alle Register ziehen wenn man die Zeit nicht zu Verfügung stellen möchte.

bearbeitet von Weingeist

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
Am 2.3.2019 um 11:26 schrieb PowerShellAdmin:

Ein guter Usecase für Perl :) *Hust*

 

Ich hätte noch Steine, könnte also den ersten werfen :-)

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
vor 42 Minuten schrieb daabm:

 

Ich hätte noch Steine, könnte also den ersten werfen :-)

Na Python ist da mittlerweile auch gut dabei von der Performance.

Gut dass ich derzeit an Python dran bin.

 

PS: Jehova Jehova ... im doppelten Sinne

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Der TO sollte sich erstmal melden, ob die vielen Tipps ihm geholfen haben.

Wenn das ganze statt zehn Stunden jetzt 30 min braucht und Ihm das reicht ist ja alles in Ordnung. Wenn das ganze in einer Minute fertig sein soll braucht man sicher eh eine andere Infrastruktur.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

@Dukel: Naja, 40GB an Textdaten nach Text zu durchsuchen ist irgendwie nie ein Spass. Wenn es mit 190MB und 1000 Adressen gerade mal 12min gegenüber 59min dauert, dann viel Spass bei 40GB. ;)

 

Das Ergebnis würde ich in deinem Beispiel auch so umschreiben, dass es ein boolscher Wert ist und nicht ein String. Erst die Auswertung ein String. Also Dics.Item('E-Mail-Addi') = true.

Am Ende dann den  Dics auswerten. Das ist mit Sicherheit schneller als String-Additionen die immer super lahm sind, insbesondere wie von daabm angemerkt wurde wenn der String immer neu allokiert werden muss. Da gibts zwar Apis die das noch schneller machen (keine Ahnung ob auch die von ihm angemerkten Streams), aber sinnvoll ist das eigentlich nie (bei solchen Datenmengen). Dann könnte man noch den Value des Dics-Eintrags testen vor dem Vergleich, ist er True (also bereits einmal gefunden) muss der Aufwendige Textvergleich für diese Adresse nicht mehr stattfinden. Er will am Ende ja nur wissen ob und nicht wie viele mal die Adresse vorhanden war.

bearbeitet von Weingeist

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Erstelle ein Benutzerkonto oder melde dich an, um zu kommentieren

Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde dich hier an.

Jetzt anmelden

Werbepartner:



×