Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Parallel.For/ForEach获得最大性能?(包括演出时间)_C#_.net_Multithreading_Performance_Parallel Processing - Fatal编程技术网

C# 如何使用Parallel.For/ForEach获得最大性能?(包括演出时间)

C# 如何使用Parallel.For/ForEach获得最大性能?(包括演出时间),c#,.net,multithreading,performance,parallel-processing,C#,.net,Multithreading,Performance,Parallel Processing,我正在尝试并行化我的web解析工具,但速度的提高似乎非常小。我有i7-2600K(8核超线程) 这里有一些代码向您展示这个想法。我只展示了Parallel.ForEach,但你明白了: List<string> AllLinks = this.GetAllLinks(); ConcurrentDictionary<string, Topic> AllTopics = new ConcurrentDictionary<string, Topic> ( ); i

我正在尝试并行化我的web解析工具,但速度的提高似乎非常小。我有i7-2600K(8核超线程)

这里有一些代码向您展示这个想法。我只展示了
Parallel.ForEach
,但你明白了:

List<string> AllLinks = this.GetAllLinks();
ConcurrentDictionary<string, Topic> AllTopics = new ConcurrentDictionary<string, Topic> ( );

int count = 0;
Stopwatch sw = new Stopwatch ( );
sw.Start ( );

Parallel.ForEach ( AllLinks, currentLink =>
{
    Topic topic = this.ExtractTopicData ( currentLink );
    this.AllTopics.TryAdd ( currentLink, topic );

    ++count;

    if ( count > 50 )
    {
        Console.WriteLine ( sw.ElapsedMilliseconds );
        count = 0;
    }
} );
首先,为什么并行模式下的“启动”时间要慢得多

除此之外,并行循环的速度是标准foreach循环的2.5倍。这正常吗

是否有一个设置我可以设置,使并行循环可以使用所有的核心

编辑:

以下是
ExtractTopicData
的基本功能:

HtmlAgilityPack.HtmlWeb web = new HtmlWeb ( );
HtmlAgilityPack.HtmlDocument doc = web.Load ( url );
IEnumerable<HtmlNode> links = doc.DocumentNode.SelectNodes ( "//*[@id=\"topicDetails\"]" );

var topic = new Topic();

foreach ( var link in links )
{
    //parse the link data
}
HtmlAgilityPack.HtmlWeb=newhtmlweb();
HtmlAgilityPack.HtmlDocument doc=web.Load(url);
IEnumerable links=doc.DocumentNode.SelectNodes(“//*[@id=\“topicDetails\”]);
var topic=新主题();
foreach(链接中的var链接)
{
//解析链接数据
}

HtmlAgilityPack.HtmlWeb
的简要阅读确认它正在使用同步
WebRequest
API。因此,您将长时间运行的任务放入线程池(通过
Parallel
)。线程池是为短期操作而设计的,这些操作会使线程快速返回到池中。IO阻塞是一个大禁忌。鉴于线程池不愿意启动新线程(因为它不是为这种用途设计的),您将受到这种行为的约束

异步获取web内容(请参阅和,以获得要使用的正确API,您必须自己进一步调查…),这样您就不会将线程池与阻塞任务捆绑在一起。然后,您可以将解码后的响应提供给HtmlAgilityPack进行解析

<>如果你真的想提高性能,你还需要考虑WebRequest不能执行异步DNS查找。在我看来,这是WebRequest设计中的一个严重缺陷

BeginGetResponse方法需要完成一些同步设置任务(例如,DNS解析、代理检测和TCP套接字连接),然后该方法才能变为异步

它使高性能下载成为真正的PITA。大约在这个时候,您可能会考虑编写自己的HTTP库,这样所有的东西都可以在不阻塞的情况下执行(因此饿死线程池)。
另外,在浏览网页时获得最大吞吐量是一件棘手的事情。根据我的经验,你得到了正确的代码,然后就被它必须通过的路由设备弄丢了。许多国内路由器根本无法胜任这项工作。

这到底是做什么的。ExtractTopicData。网络请求?哪个API?抱歉忘了提一下,它使用html敏捷包并进行一些解析。上面添加了详细信息。此外,您正在以非安全的方式变异局部变量(计数)。这将是不可靠的。@Juda,这会影响计时结果吗?@JoanVenge大部分时间都花在I/O上。本质上,你的线程都在等待下载完成。这不会占用太多CPU。谢谢,我如何异步获取我的web内容?我有我所有的链接预生成。这就是你的意思吗?基本上我有1000个链接可以解析,所以我可以使用解析后的信息进一步获取我需要的数据,比如主题标题、主题所有者、日期等,通过解析html agility pack提供给我的数据。感谢spender,这是有意义的。顺便说一句,我实现了web响应并将其传递给html agility pack,但性能并没有那么好。最初的GetAllLinks快了2倍,但其他的还是一样的,cpu使用率仍然很低(3%)。最后,您知道关于
下载StringAsync
?我应该用这个来代替下载字符串吗?
HtmlAgilityPack.HtmlWeb web = new HtmlWeb ( );
HtmlAgilityPack.HtmlDocument doc = web.Load ( url );
IEnumerable<HtmlNode> links = doc.DocumentNode.SelectNodes ( "//*[@id=\"topicDetails\"]" );

var topic = new Topic();

foreach ( var link in links )
{
    //parse the link data
}