【发布时间】:2022-08-06 19:28:44
【问题描述】:
我正在运行一个具有 24 个线程 (5900X) 的 CPU,启动 20 个任务来执行一个完全受 CPU 限制的操作,但 CPU 负载最高达到 10%。试图看看是否有人可以阐明这是否是我误解了任务如何线程化,或者执行处理的库(HtmlAgilityPack)是否有问题?
这是一个有点复杂的例子:
public async static Task TestHtmlAgilityPack(bool loadHtml = true)
{
// \"basePath\" is a folder has approx 20 folders each containing approx 3000 files (20 tasks * 3,000 files = 60k overall)
var dirs = Directory.GetDirectories(basePath);
List<Task> tasks = new();
var strs = new ConcurrentBag<string>();
foreach (var dir in dirs)
{
tasks.Add(Task.Run(() =>
{
foreach (var file in Directory.GetFiles(dir, \"*.html\")) // Each of the 20 tasks processes approx 3000 files
{
var html = File.ReadAllText(file);
strs.Add(html.Substring(1, 1000));
if (loadHtml)
{
var doc = new HtmlDocument();
doc.LoadHtml(html);
}
}
}));
}
await Task.WhenAll(tasks);
Console.WriteLine(strs.Last());
}
如果我在没有 LoadHtml 的情况下运行它,它会在 15 秒内完成,所以 IO 访问时间是微不足道的。使用 LoadHtml 现在需要 20 分钟,我知道将 HTML 解析为可查询的表单需要时间,这很好/预期,但令人困惑的是它(应该?)是一个纯粹的 CPU 密集型操作,它\'不等待任何东西。为什么 CPU 在 10% 处达到峰值,而不是使用接近 80% 的值,因为在 24 线程 CPU 上通过 CPU 密集型操作加载 20 个线程?
这是否表明 LoadHtml 方法或其他方法效率低下?
-
您没有使用“ASYNC”,因此每个任务都会阻塞,直到任务完成。
-
@jdweng 不在哪里使用异步? 20 个任务中的每一个都应该在自己的线程上执行一个长时间的 CPU 密集型操作(处理 3000 个文件)。我不明白为什么他们会在跑步过程中互相阻挡,只有在我等待他们全部完成时才结束,这就是我想要的?
-
任务不会自动异步运行。任务是单独的线程,但在下一个线程启动之前运行完成。请参阅以下内容:stackoverflow.com/questions/20304258/…
-
@HansPassant 谢谢!!我的google-fu一定很弱,没有发现这个问题。不确定此更改的全部后果是什么,但我将垃圾收集器从默认设置切换到服务器,现在它的速度提高了 10-15 倍。我每天运行的线程化 HTML 分析任务过去需要 37 分钟,现在需要 3 分钟,我希望在问这个问题时能提高一点速度,但没想到会接近这个!再次感谢
标签: c# multithreading task-parallel-library html-agility-pack