Why is DirectorySearcher so slow when compared to PrincipalSearcher?

后端 未结 2 1291
星月不相逢
星月不相逢 2021-01-05 15:24

Our application has a process which fetches all users from Active Directory and updates the relevant SQL tables with their information. The process at nights and it was writ

相关标签:
2条回答
  • 2021-01-05 15:44

    While writing this question I was tinkering with the test code and managed to find the issue. By providing the domain address when constructing the root DirectoryEntry:

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

    The search with DirectorySearcher outperformed that of PrincipalSearcher. I'm not exactly sure why - perhaps it's something to do with where the searcher looks for the results - but it definitely boosted the search speed.

    0 讨论(0)
  • 2021-01-05 16:11

    Take a look at my question and answer on the differences between the two methods. PrincipalSearcher is merely a wrapper around DirectorySearcher. It was designed to make it easier to work with Active Directory while providing some automated speed enhancements. DirectorySearcher can be much faster than PrincipalSearcher, but it requires a bit more work.

    The main reason you're seeing slow behavior from your "old stuff" code is that in when you used PrincipalSearcher in "new stuff", you got the underlying DirectorySearcher and fed its PropertiesToLoad collection. You did not do that in your "old stuff" code.

    var properties = new[] { "cn", "name", "distinguishedname", "surname", "title", "displayname" };
    //...
    var underlying = searcher.GetUnderlyingSearcher() as DirectorySearcher;
    //...
    underlying.PropertiesToLoad.AddRange(properties);
    

    As a result, your "old stuff" code was pulling every AD attribute for matched results (i.e. significantly more data being transferred), while your implementation using PrincipalSearcher was only reading 6 attributes.

    Doing that when using PrincipalSearcher is also generally not necessary as it handles caching and picking of attributes on its own. Really, when working with PrincipalSearcher the only time you need to get the underlying DirectorySearcher is to set the PageSize since PrincipalSearcher doesn't provide a standard way to set it.

    I suspect the reason you saw an improvement when specifying the domain is that it didn't have to do any work to figure out the domain name. You unfairly give "new stuff" a head start in that regards because you made the PrincipalContext before you started the clock so to speak.

    // 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; // you should have done this BEFORE setting `context`. 
    

    Some other things I noticed in your code that would actually skew the timing in the opposite direction is that in "new stuff", you don't do any filtering, and the initialization of your delegated thread to show the progress occurs AFTER you recorded the start time.

    0 讨论(0)
提交回复
热议问题