循环原子馈送的最快方法

Ron*_*Ron 2 c# rss for-loop atom-feed

我正在编写一个对性能非常关键的程序。我正在轮询一个通常有大约 50 个条目的 Atom feed。我需要解析它才能尽快获得 uri 链接。

目前我正在这样做:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我从许多来源了解到,使用 for 循环比使用 foreach 快得多,因此我尝试实现这一点,但不断收到一些错误,指出无法将索引应用于 SyndicateItem。这似乎是因为 SyndicateItem 是 IEnumerable。

因此,这给我留下了两个问题:1.)是否有更好、更高效/更快的方法来做到这一点2.)我目前是否正在实施最佳解决方案?

Str*_*ior 5

绝大多数时间可能都花在了往返取饲料上。通常,网络延迟时间将使迭代集合所需的时间相形见绌。

但是,您的数据可能feedContent.Items不会立即完全加载到内存中,因此迭代Reverse此集合可能会导致比您需要的更多的开销。我个人建议使用 LINQ 语句在一次传递中获取所需的项目,然后调用.ToList()将结果放入内存中的集合中,该集合在调用之前可以轻松逆转.Reverse()

var uris = 
    (from item in feedContent.Items
    where item.Title.Text.Contains(searchTerm)
    from link in item.Links
    select link.Uri)
    .ToList()
    .Reverse();
Run Code Online (Sandbox Code Playgroud)

或者,如果您只对单个 URI 感兴趣(您的代码使您看起来只是想在第一个匹配中结束第一个 URI),您也可以直接调用并完全.FirstOrDefault()跳过 and :ReverseToList

var uris = 
    (from item in feedContent.Items
    where item.Title.Text.Contains(searchTerm)
    from link in item.Links
    select link.Uri)
    .FirstOrDefault()
Run Code Online (Sandbox Code Playgroud)

更新

我稍微研究了一下这个程序(正如我所怀疑的),该程序大约 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)
Run Code Online (Sandbox Code Playgroud)

重申一下,这不会给您带来任何显着的性能改进,但代码更能表达您真正想要做的事情,因此更容易维护。