2017-07-27 1 views
0

Unsere Anwendung verfügt über einen Prozess, der alle Benutzer aus Active Directory abruft und die relevanten SQL-Tabellen mit ihren Informationen aktualisiert. Der Prozess in der Nacht und es wurde vor ein paar Jahren geschrieben - so ist es Legacy-Code, der funktioniert und "wenn es nicht kaputt ist, repariere es nicht". Wir führen jedoch eine neue Funktion in unsere Anwendung ein, die Änderungen an diesem Code erfordert, und da sie seit Jahren nicht mehr berührt wurde, dachte ich, ich könnte sie genauso gut aufräumen.Warum ist DirectorySearcher im Vergleich zu PrincipalSearcher so langsam?

Dieser Prozess läuft NUR während der Nacht mit Ausnahme von seltenen Serverfehlern, in diesem Fall müssen wir es manuell während des Tages ausführen. Der Prozess verwendet die gute alte System.DirectoryServices-Bibliothek, um seine Arbeit zu erledigen, und obwohl es funktioniert, läuft es ziemlich langsam.

Ich dachte über die neuere System.DirectoryServices.AccountManagement Bibliothek statt verwenden, so begann ich den gesamten Prozess Umschreiben (ein paar hundert Zeilen Code) und ich war erstaunt zu sehen, dass PrincipalSearcherdramatischDirectorySearcher trifft.

Ich habe versucht, aus dem Grund zu suchen und kam auf the following SO answer, die einen Vergleich zwischen den beiden gibt, die besagt, dass DirectorySearcher als PrincipalSearcher schneller sein sollte.

ich ein Testprojekt gefeuert zu vergewissern, dass ich nicht halluziniert wurde:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // New stuff 
     var context = new PrincipalContext(ContextType.Domain, "mydomain.com"); 
     var properties = new[] { "cn", "name", "distinguishedname", "surname", "title", "displayname" }; 
     var i = 0; 
     var now = DateTime.Now; 

     new Thread(delegate() 
     { 
      while (true) 
      { 
       Console.Write("\r{0} ms, {1} results", (DateTime.Now - now).TotalMilliseconds, i); 
       Thread.Sleep(1000); 
      } 
     }).Start(); 

     using (var searcher = new PrincipalSearcher(new UserPrincipal(context))) 
     { 
      var underlying = searcher.GetUnderlyingSearcher() as DirectorySearcher; 
      underlying.PageSize = 1000; 
      underlying.PropertiesToLoad.Clear(); 
      underlying.PropertiesToLoad.AddRange(properties); 
      underlying.CacheResults = false; 

      using (var results = searcher.FindAll()) 
      { 
       foreach (var result in results) 
       { 
        i++; 
       } 
      } 
     } 

     Console.WriteLine("It took {0}", (DateTime.Now - now).TotalMilliseconds); 
     now = DateTime.Now; 
     i = 0; 

     // Old stuff 
     var root = new DirectoryEntry("LDAP://DC=mydomain,DC.com"); 
     var filter = "(&(objectCategory=user)(objectClass=user))"; 

     using (var searcher = new DirectorySearcher(root, filter, properties)) 
     { 
      searcher.PageSize = 1000; 
      searcher.CacheResults = false; 

      using (var results = searcher.FindAll()) 
      { 
       foreach (var result in results) 
       { 
        i++; 
       } 
      } 
     } 

     Console.WriteLine("It took {0}", (DateTime.Now - now).TotalMilliseconds); 
    } 
} 

einige tausend Benutzer abfragen, waren die Ergebnisse um 0.9ms pro Benutzer mit PrincipalSearcher (ca. 30 Sekunden für ~ 34k-Benutzer) und ungefähr 5,2 ms pro Benutzer mit DirectorySearcher (ungefähr 2 Minuten und 30 Sekunden für ~ 34k Benutzer) - PrincipalSearcher ist fast sechsmal schneller.

Ich versuchte Debugging und Vergleich der PrincipalSearcher zugrunde liegenden DirectorySearcher mit dem einen, den ich erstellt und sie schienen ziemlich ähnlich.

Ich versuchte weiter nach vorne zu prüfen und es scheint, dass, wenn ich die Suche Wurzel aus der PrincipalSearcher ‚s zugrunde liegenden Sucher verwenden, dann ist die DirectorySearcher schaffe ich tatsächlich die PrincipalSearcher trifft:

 // ... 

     DirectoryEntry psRoot; 

     using (var searcher = new PrincipalSearcher(new UserPrincipal(context))) 
     { 
      var underlying = searcher.GetUnderlyingSearcher() as DirectorySearcher; 
      psRoot = underlying.SearchRoot; 

      // ... 
     } 

     // ... 

     using (var searcher = new DirectorySearcher(psRoot, filter, properties)) 
     { 
      // ... 
     } 

während des Debuggens fand ich heraus, dass Die Suchwurzeln sind weitgehend gleich - dh sie repräsentieren die gleiche Domäne.

Was könnte die Suchgeschwindigkeit so verlangsamen?

Antwort

2

Während ich diese Frage geschrieben habe, habe ich an dem Testcode herumgebastelt und es geschafft, das Problem zu finden. Durch die Bereitstellung der Domain-Adresse, wenn die Root-Konstruktion DirectoryEntry:

// var root = new DirectoryEntry("LDAP://DC=mydomain,DC.com"); 
var root = new DirectoryEntry("LDAP://mydomain.com/DC=mydomain,DC.com"); 

Die Suche mit DirectorySearcher übertraf die von PrincipalSearcher. Ich weiß nicht genau, warum - vielleicht hat es etwas damit zu tun, wo der Sucher nach den Ergebnissen sucht - aber es hat definitiv die Suchgeschwindigkeit erhöht.

Verwandte Themen