tim3510 0 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 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 Zitieren Link zu diesem Kommentar
zahni 554 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 (bearbeitet) 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 27. Februar 2019 von zahni Zitieren Link zu diesem Kommentar
BOfH_666 577 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 Den Hinweis von Lee_Dailey schon probiert .... ? https://stackoverflow.com/questions/54901996/powershell-performance Zitieren Link zu diesem Kommentar
testperson 1.677 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 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 Zitieren Link zu diesem Kommentar
tim3510 0 Geschrieben 27. Februar 2019 Autor Melden Teilen Geschrieben 27. Februar 2019 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 :( Zitieren Link zu diesem Kommentar
zahni 554 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 Du hast doch oben das Beispiel. Du packst die Log-Datei in einer foreach-Schleife und dort verschachtelt eine Foreach für das Array. Zitieren Link zu diesem Kommentar
BOfH_666 577 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 Verschachtelte Schleife brauchst Du eigentlich nicht unbedingt. Du kannst mit dem Statement -in oder -contains prüfen, ob ein einzelnes Element in einem Array enthalten ist. Das sollte flotter gehen als ein nested loop. Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 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. Zitieren Link zu diesem Kommentar
daabm 1.354 Geschrieben 27. Februar 2019 Melden Teilen Geschrieben 27. Februar 2019 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... Zitieren Link zu diesem Kommentar
PowerShellAdmin 169 Geschrieben 2. März 2019 Melden Teilen Geschrieben 2. März 2019 Ein guter Usecase für Perl :) *Hust* Zitieren Link zu diesem Kommentar
Weingeist 159 Geschrieben 11. März 2019 Melden Teilen Geschrieben 11. März 2019 (bearbeitet) 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 11. März 2019 von Weingeist Zitieren Link zu diesem Kommentar
daabm 1.354 Geschrieben 11. März 2019 Melden Teilen Geschrieben 11. März 2019 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 Zitieren Link zu diesem Kommentar
PowerShellAdmin 169 Geschrieben 11. März 2019 Melden Teilen Geschrieben 11. März 2019 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 Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 11. März 2019 Melden Teilen Geschrieben 11. März 2019 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. Zitieren Link zu diesem Kommentar
Weingeist 159 Geschrieben 11. März 2019 Melden Teilen Geschrieben 11. März 2019 (bearbeitet) @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 11. März 2019 von Weingeist Zitieren Link zu diesem Kommentar
Empfohlene Beiträge
Schreibe einen Kommentar
Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.