gpt4 book ai didi

c# - 与 PrincipalSearcher 相比,为什么 DirectorySearcher 这么慢?

转载 作者:行者123 更新时间:2023-11-30 15:17:57 29 4
gpt4 key购买 nike

我们的应用程序有一个从 Active Directory 中获取所有用户并使用他们的信息更新相关 SQL 表的过程。晚上的过程,它是几年前写的——所以它是有效的遗留代码,“如果它没有被破坏,就不要修复它”。然而,我们正在向我们的应用程序引入一项新功能,它需要修改此代码,并且由于它多年未被触及,我想我不妨稍微清理一下。

除了罕见的服务器故障外,该进程仅在夜间运行,在这种情况下,我们必须在白天手动运行它。该进程使用旧的 System.DirectoryServices 库来完成它的工作,尽管它可以工作,但运行速度相当慢。

我考虑改用更新的 System.DirectoryServices.AccountManagement 库,所以我开始重写整个过程(几百行代码),我惊讶地看到 PrincipalSearcher 显着优于DirectorySearcher

我一直在寻找原因并找到了 the following SO answer它给出了两者之间的比较,指出 DirectorySearcher 应该比 PrincipalSearcher 更快。​​

我启动了一个测试项目以确保我没有产生幻觉:

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);
}
}

查询数千名用户,使用 PrincipalSearcher 时每位用户的结果约为 0.9 毫秒(约 34k 用户大约需要 30 秒),使用 DirectorySearcher 时每位用户约为 5.2 毫秒(约 34k 用户大约需要 2 分 30 秒)- PrincipalSearcher 几乎快了六倍。

我尝试调试并比较 PrincipalSearcher 的底层 DirectorySearcher 与我创建的那个,它们看起来非常相似。

我尝试进一步检查,似乎如果我使用 PrincipalSearcher 的底层搜索器的搜索根,那么我创建的 DirectorySearcher 实际上优于 PrincipalSearcher:

        // ...

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))
{
// ...
}

调试时我发现搜索根基本相同 - 即,它们代表相同的域。

什么会导致搜索速度变慢?

最佳答案

看看my question and answer on the differences between the two methods . PrincipalSearcher 只是 DirectorySearcher 的包装器。它旨在使使用 Active Directory 更容易,同时提供一些自动速度增强。 DirectorySearcher 可以比 PrincipalSearcher 快得多,但它需要更多的工作。

你看到“旧东西”代码行为缓慢的主要原因是当你在“新东西”中使用 PrincipalSearcher 时,你得到了底层的 DirectorySearcher 并提供其 PropertiesToLoad 集合。你没有在你的“旧东西”代码中这样做。

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

因此,您的“旧东西”代码正在提取匹配结果的每个 AD 属性(即传输的数据明显更多),而您使用 PrincipalSearcher 的实现仅读取 6 个属性。

在使用 PrincipalSearcher 时通常也没有必要这样做,因为它会自行处理缓存和选择属性。实际上,在使用 PrincipalSearcher 时,您唯一需要获取底层 DirectorySearcher 的时间是设置 PageSize,因为 PrincipalSearcher 没有提供标准的设置方法。

我怀疑您在指定域时看到改进的原因是它不需要做任何工作来找出域名。在这方面,您不公平地让“新东西”先行一步,因为可以这么说,您在开始计时之前创建了 PrincipalContext

// 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`.

我在您的代码中注意到的其他一些事情实际上会使时间向相反的方向倾斜,即在“新内容”中,您不进行任何过滤,并且委托(delegate)线程的初始化以显示进度发生在 AFTER你记录了开始时间。

关于c# - 与 PrincipalSearcher 相比,为什么 DirectorySearcher 这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45357892/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com