2017-09-07 3 views
0

Performace Ich habe zwei Listen in Powershell mit einer großen Menge von Daten:
Powershell Merge 2 Listen

  • $ Byods MACs und Benutzernamen enthält, mit etwa 5000 Artikel
  • $ DHCPLeases MACs und IPs mit etwa 3000 enthält, Artikel

ich möchte eine neue Liste mit Benutzernamen und IP-Adressen erstellen, in dem die Byods Liste führt, und die IP-Adressen werden von den DHCPleases, nur containg Datensätze gefunden, die eine Übereinstimmung gefunden (a LEFT JOIN?)

Ich habe eine foreach-Schleife erstellt, die den Job erledigt. Es dauert jedoch sehr viel Zeit (> 30 min).

Ich bin mir sicher, dass dies schneller sein kann. Jemand?

$UserByods = @() 
foreach ($lease in $DHCPLeases) 
{ 
    $MAC = [string]$lease.MAC 
    $UserByod = @() 
    $UserByod = $Byods | where {$_.MAC -eq $MAC} 
    if (($UserByod | measure).count -eq 1) { 
     $ByodIP = New-Object -TypeName PSObject 
     $ByodIP | Add-Member -Name 'User' -MemberType Noteproperty -Value $UserByod.Username 
     $ByodIP | Add-Member -Name 'IP' -MemberType Noteproperty -Value $lease.IP 
     $UserByods += $ByodIP 
    } 
} 
+0

Um zu beginnen: ersetzen Sie das $ userbyods + = mit etwas wie einem list.add() (zuerst erstellen Sie eine neue Liste). Mit + = wird bei jeder Iteration eine Kopie des Arrays erstellt. Zweitens: Sie können Schritte mit einer Stoppuhr durchführen, um die Leistung zu überprüfen und um zu sehen, welche Schritte eine "lange" Zeit benötigen. – bluuf

Antwort

4

Eine Reihe von Verbesserungen kann hier vorgenommen werden. Zunächst einmal, verwenden Sie nicht Add-Member, um die Objekte zu konstruieren, es wird deutlich langsamer als die Angabe der Eigenschaften im Vordergrund.

Sie sollten auch vermeiden, den Additionsoperator (+=) für eine Sammlung zu verwenden, da dadurch das zugrunde liegende Array in der Größe verändert wird, was eine recht speicherintensive Operation ist.

schließlich eine Hash-Tabelle für die MAC-Korrelation verwenden, wird es viel schneller als durch alle 5000 Einträge 3000 mal Looping (was ...| Where {...} grundsätzlich der Fall ist):

4

Das Anhängen an ein Array in einer Schleife ist langsam. Geben Sie einfach Ihre benutzerdefinierten Objekte in der Schleife aus und sammeln Sie die Schleifenausgabe in der Variablen $UserByods. Lineare Lesevorgänge auf einer Liste sind ebenfalls langsam. Erstellen Sie besser eine Hashtabelle von $Byods, damit Sie Geräte nach ihrer MAC-Adresse suchen können.

$tbl = @{} 
$Byods | ForEach-Object { $tbl[$_.MAC] = $_ } 

$UserByods = foreach ($lease in $DHCPLeases) { 
    New-Object -TypeName PSObject -Property @{ 
     'User' = $tbl[$lease.MAC].Username 
     'IP' = $lease.IP 
    } 
} 
+1

tolle köpfe denken gleich, lol –

+0

Whow, danke euch beiden so sehr! Dies reduzierte das Skript auf nur 2 Sekunden! – Sjoerdvw

0

Ich habe nicht Ihre Liste aber Ich frage mich, wie mein Join-Object Cmdlet auf diesem ausführt.
Der Befehl so etwas wie dies sein sollte:

$Byods | LeftJoin $DHCPLeases Mac 

Ich habe in der Leistung etwas Mühe ruhig gestellt, aber da es eine allgemeine Lösung ist es vielleicht nicht mit der spezifischen Lösung hier gegeben konkurrieren kann ...