学无先后达者为师!
不忘初心,砥砺前行。

解决使用 Html Agility Pack 解析网页时并行优化无效的问题

HtmlAgilityPack 是一个 HTML 解析库,用于 .NET 平台。它允许开发者以类似于解析 XML 的方式,轻松地解析和操作 HTML 文档。这个库特别适合处理非标准的 HTML,例如那些格式不正确或包含错误的 HTML 文档。

从原理上说,解析是一个 CPU 密集型操作。在计算资源充裕的情况下,使用多线程并行可以加快处理速度。

以下代码展示了两个场景:

  • 使用一个线程解析 1000 个页面
  • 使用 8 个线程解析 1000 个页面(总量 1000 个,测试机器上的 CPU 有 8 个内核)。
string html = File.ReadAllText("PATH");
//One thread
for (int i = 0; i < 1000; i++)
   new HtmlDocument().LoadHtml(html);
//Several threads
Parallel.For(0, 1000, (int i) => new HtmlDocument().LoadHtml(html));

然而实际的情况是:尽管多线程版本消耗了 2 ~ 3 倍的 CPU,但所花费的时间大致相同。而且 CPU 占用率一直维持在 30% 以下。即便更换了要处理的页面,或者内核数量更多的电脑,情况都差不多。

如何解决

开启更多的线程并不会提升处理的速度,这让我开始怀疑是不是存在锁的问题。遗憾的是没有在源代码中找到 lock ,但是发现了一个 Issues:

https://github.com/zzzprojects/html-agility-pack/issues/191

用户 BenoitSa 提到:

在使用 Profiler 工具对多线程程序进行分析之后,发现程序可能存在内存瓶颈。根据他的观察,有大约 50% 的 CPU 时间耗费在了内存分配上。

这和使用的 GC 类型有关,向 App.config 增加以下代码可以解决该问题:

  <runtime>
    <gcServer enabled="true"/>
    <gcConcurrent enabled="false" />
  </runtime>

适配 .NET 8.0

我的程序是一个使用 .NET 8.0 框架的控制台,增加 App.config 文件之后并没有效果。于是,我找到了微软的官方文档:

https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector

根据文档所述,可以通过环境变量、runtimeconfig.json 文件或项目文件来指定程序使用 Server 版本。我选择修改项目文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <ServerGarbageCollection>true</ServerGarbageCollection>
  </PropertyGroup>

</Project>

问题得以解决:处理速度快了不少,CPU 占用维持在了 70% 左右。

赞(2) 打赏
未经允许不得转载:码农很忙 » 解决使用 Html Agility Pack 解析网页时并行优化无效的问题

评论 抢沙发

给作者买杯咖啡

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册