Why is DirectorySearcher so slow when compared to PrincipalSearcher?(与 PrincipalSearcher 相比,为什么 DirectorySearcher 如此缓慢?)
问题描述
我们的应用程序有一个从 Active Directory 获取所有用户并使用他们的信息更新相关 SQL 表的过程.晚上的过程,它是几年前写的 - 所以它是遗留代码,并且如果它没有损坏,就不要修复它".但是,我们正在向我们的应用程序引入一项新功能,该功能需要修改此代码,而且由于多年未触及它,我想我不妨稍微清理一下.
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 written a few years ago - so it's legacy code which works and "if it ain't broken, don't fix it". However we're introducing a new feature to our application which requires modifications to this code, and since it hasn't been touched for years I thought I might as well clean it up a little.
上述进程仅在夜间运行,除非服务器出现罕见故障,在这种情况下,我们必须在白天手动运行.该进程使用旧的 System.DirectoryServices
库来完成它的工作,虽然它可以工作,但运行速度很慢.
Said process runs ONLY during the night except for rare server faults, in which case we have to run it manually during the day. The process uses the good old System.DirectoryServices
library to do its job, and although it works, it runs quite slowly.
我想改用更新的 System.DirectoryServices.AccountManagement
库,所以我开始重写整个过程(几百行代码),我很惊讶地看到 PrincipalSearcher
显着优于DirectorySearcher
.
I thought about using the newer System.DirectoryServices.AccountManagement
library instead, so I started rewriting the whole process (a few hundreds lines of code) and I was amazed to see that PrincipalSearcher
dramatically outperforms DirectorySearcher
.
我一直在试图寻找原因并发现了以下 SO 答案,它给出了二,声明 DirectorySearcher
应该比 PrincipalSearcher
更快.
I've been trying to look for the reason and came upon the following SO answer which gives a comparison between the two, stating that DirectorySearcher
should be faster than PrincipalSearcher
.
我启动了一个测试项目以确保我没有出现幻觉:
I fired up a test project to make sure I was not hallucinating:
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("
{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
几乎快了六倍.
Querying some thousand users, the results were around 0.9ms per user with PrincipalSearcher
(around 30 seconds for ~34k users) and around 5.2ms per user with DirectorySearcher
(around 2 minutes and 30 seconds for ~34k users) - PrincipalSearcher
being almost six times faster.
我尝试调试并将 PrincipalSearcher
的底层 DirectorySearcher
与我创建的进行比较,它们看起来非常相似.
I tried debugging and comparing the PrincipalSearcher
's underlying DirectorySearcher
with the one I created and they seemed pretty much similar.
我尝试进一步检查,似乎如果我使用来自 PrincipalSearcher
的底层搜索器的搜索根,那么我创建的 DirectorySearcher
实际上优于 PrincipalSearcher
:
I tried examining further ahead and it seems that if I use the search root from the PrincipalSearcher
's underlying searcher, then the DirectorySearcher
I create actually outperforms the 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))
{
// ...
}
在调试时我发现搜索根基本相同 - 即它们代表相同的域.
While debugging I found out that the search roots are largely the same - i.e., they represent the same domain.
什么会导致搜索速度变慢?
What could cause the search speed to slow down like this?
推荐答案
在写这个问题时,我正在修补测试代码并设法找到了问题.通过在构建根目录时提供域地址DirectoryEntry
:
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");
DirectorySearcher
的搜索性能优于 PrincipalSearcher
.我不确定为什么 - 也许这与搜索者查找结果的位置有关 - 但它确实提高了搜索速度.
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.
这篇关于与 PrincipalSearcher 相比,为什么 DirectorySearcher 如此缓慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:与 PrincipalSearcher 相比,为什么 DirectorySearcher 如此
基础教程推荐
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- 创建属性设置器委托 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01