C# 通过atom提要循环的最快方法
我正在编写一个对性能非常关键的程序。我正在轮询一个atom提要,它通常有大约50个条目。我需要解析通过这个可以得到尽可能快的uri链接 目前我正在这样做:C# 通过atom提要循环的最快方法,c#,for-loop,rss,atom-feed,C#,For Loop,Rss,Atom Feed,我正在编写一个对性能非常关键的程序。我正在轮询一个atom提要,它通常有大约50个条目。我需要解析通过这个可以得到尽可能快的uri链接 目前我正在这样做: var feedUrl = "my path"; using (var feedReader = XmlReader.Create(feedUrl)) { var feedContent = SyndicationFeed.Load(feedReader); if (null == feedContent) return n
var feedUrl = "my path";
using (var feedReader = XmlReader.Create(feedUrl))
{
var feedContent = SyndicationFeed.Load(feedReader);
if (null == feedContent) return null;
foreach (var item in feedContent.Items.Reverse())
{
if (item.Title.Text.Contains("Some text I am looking for"))
{
foreach (var link in item.Links)
{
uri = link.Uri;
}
}
}
}
我从许多资料中了解到,使用for循环比使用foreach快得多,所以我正在尝试实现这一点,但不断出现一些错误,即无法对SyndicationItem应用索引。这似乎是因为SyndicationItem是一个IEnumerable
这给我留下了两个问题:
1.)是否有更好、更高效/更快的方法
2.)我目前实施的是最佳解决方案吗?绝大多数时间可能都花在从一开始就获取提要的往返过程中。通常,网络延迟时间会使迭代集合所需的时间缩短 但是,您的
feedContent.Items
可能没有立即完全加载到内存中,因此对该集合的反向
进行迭代可能会导致比您需要的开销大得多。我个人建议使用LINQ语句在一次传递中获取所需的项,然后调用.ToList()
将结果放入内存中的集合中,在调用.Reverse()
之前,该集合很容易恢复
或者,如果您只对一个URI感兴趣(您的代码使它看起来像您只是试图在第一次匹配中得到第一个URI),您也可以调用.FirstOrDefault()
并完全跳过反向和ToList
:
var uris =
(from item in feedContent.Items
where item.Title.Text.Contains(searchTerm)
from link in item.Links
select link.Uri)
.FirstOrDefault()
使现代化
我玩了一点,并且(正如我所怀疑的)这个程序大约95%的成本(针对Blogger上有25个项目的提要进行测试)被调用XmlReader.Create()
和SyndicationFeed.Load()
占用。尝试优化for
循环就像用千分尺测量、用蜡笔标记和用斧头切割一样
更新2
回应你的评论:是的,有一种方法,而且非常简单
var updateTimesByUri =
(from item in feedContent.Items
where item.Title.Text.Contains(searchTerm)
from link in item.Links
select new {link.Uri, item.LastUpdatedTime})
.ToDictionary(l => l.Uri, l => l.LastUpdatedTime)
只是重申一下,这不会给您带来任何显著的性能改进,但是代码更能表达您真正想要做的事情,因此更易于维护。绝大多数时间可能都花在一开始就获取提要的往返过程中。通常,网络延迟时间会使迭代集合所需的时间缩短
但是,您的feedContent.Items
可能没有立即完全加载到内存中,因此对该集合的反向
进行迭代可能会导致比您需要的开销大得多。我个人建议使用LINQ语句在一次传递中获取所需的项,然后调用.ToList()
将结果放入内存中的集合中,在调用.Reverse()
之前,该集合很容易恢复
或者,如果您只对一个URI感兴趣(您的代码使它看起来像您只是试图在第一次匹配中得到第一个URI),您也可以调用.FirstOrDefault()
并完全跳过反向和ToList
:
var uris =
(from item in feedContent.Items
where item.Title.Text.Contains(searchTerm)
from link in item.Links
select link.Uri)
.FirstOrDefault()
使现代化
我玩了一点,并且(正如我所怀疑的)这个程序大约95%的成本(针对Blogger上有25个项目的提要进行测试)被调用XmlReader.Create()
和SyndicationFeed.Load()
占用。尝试优化for
循环就像用千分尺测量、用蜡笔标记和用斧头切割一样
更新2
回应你的评论:是的,有一种方法,而且非常简单
var updateTimesByUri =
(from item in feedContent.Items
where item.Title.Text.Contains(searchTerm)
from link in item.Links
select new {link.Uri, item.LastUpdatedTime})
.ToDictionary(l => l.Uri, l => l.LastUpdatedTime)
重申一下,这不会给您带来任何显著的性能改进,但代码更能表达您真正想要做的事情,因此更易于维护。您错了。使用for
循环和foreach
循环之间的差异是如此之小,以至于它变得毫无意义。你应该使用更具可读性的语言。我同意DBM的观点,如果循环的性能差异足够大,那么你可能使用了错误的语言。你错了。使用for
循环和foreach
循环之间的差异是如此之小,以至于它变得毫无意义。你应该使用更具可读性的方法。我同意DBM的观点,如果循环的性能差异足够大,那么你可能使用了错误的语言。条带化-我正在尝试实现这个解决方案,所以我只需在第一次通过时将其全部加载到内存中。然而,在我完成它的过程中,我还需要获得每个项目的最新更新时间。有没有一种方法可以使用这个linq进程构建一个以MyURI为键、UpdateTime为值的哈希表?谢谢您的编辑。我收到一个错误,因为SyndicationLink不包含LastUpdateTime。此定义位于“item”级别,而不是xml的item.Links级别。这就是我在尝试设置时遇到的问题。@Ron:我根据您所说的稍微更改了代码示例。条带化-我正在尝试实现此解决方案,所以我只是在第一次通过时将其全部加载到内存中。然而,在我完成它的过程中,我还需要获得每个项目的最新更新时间。有没有一种方法可以使用这个linq进程构建一个以MyURI为键、UpdateTime为值的哈希表?谢谢您的编辑。我收到一个错误,因为SyndicationLink不包含LastUpdateTime。此定义位于“item”级别,而不是xml的item.Links级别。这就是我在尝试设置时遇到的问题。@Ron:我根据您所说的稍微更改了代码示例。