You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多任务执行CPU密集型操作仅占10%CPU?寻求原因排查

问题:CPU密集型HTML解析任务CPU负载仅10%的原因排查

我使用24线程的5900X CPU,启动20个Task执行一项本应完全属于CPU密集型的HTML解析操作,但CPU负载最高仅达到10%。想了解是对Task线程模型的理解有误,还是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分钟,但CPU负载峰值仅10%,远低于24线程CPU运行20个CPU密集型任务预期的约80%。

分析与排查方向
  • 核心原因大概率是ConcurrentBag<string>的锁竞争:
    strs.Add是线程安全操作,但当20个线程同时高频调用该方法时,会产生严重的锁竞争——大量线程会处于等待锁释放的状态,而非执行CPU密集的解析逻辑,直接拉低整体CPU利用率。
    验证方法:注释掉strs.Add(html.Substring(1, 1000));这一行后重新测试,若CPU负载明显上升,即可确认锁竞争是问题根源。

  • HtmlAgilityPack的潜在同步瓶颈:
    部分版本的HtmlAgilityPack在解析过程中可能存在全局锁或共享资源的同步逻辑,导致多线程无法真正并行执行解析操作。但这个概率低于锁竞争,建议先排除锁竞争问题后再验证。

  • Task线程调度的小概率影响:
    虽然20个Task理论上能填满24线程的CPU,但如果线程池因历史操作残留(比如之前的IO线程未及时回收)导致线程分配不足,也可能影响负载。但结合你IO可忽略的前提,这个可能性极低。


内容的提问来源于stack exchange,提问作者Zak123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:24:27