Самый быстрый способ перебрать атомную подачу - PullRequest
1 голос
/ 02 февраля 2012

Я пишу программу, которая очень важна для производительности.Я опрашиваю фид атомов, который обычно содержит около 50 записей.Мне нужно разобраться в этом, можно получить ссылку на 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;
            }
        }
    }
}

Я прочитал из многих источников, что использование цикла for гораздо быстреечем использовать foreach, поэтому я пытаюсь реализовать это, но продолжаю получать некоторые ошибки, которые говорят, что нельзя применить индексацию к SyndicationItem.Кажется, это происходит потому, что SyndicationItem является IEnumerable.

Так что у меня остается два вопроса: 1.) Есть ли лучший, более эффективный / быстрый способ сделать это 2.) В настоящее время я внедряю лучшее решение?

1 Ответ

4 голосов
/ 02 февраля 2012

Подавляющее большинство времени, скорее всего, тратится в оба конца, чтобы забрать корм в первую очередь. Как правило, время задержки в сети сокращает время, необходимое для перебора коллекции.

Однако возможно, что ваш 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();

Или, если вы просто заинтересованы в одном URI (ваш код выглядит так, как будто вы просто пытаетесь получить первый URI в первом совпадении), вы можете просто позвонить .FirstOrDefault() и полностью пропустите Reverse и ToList:

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

Обновление

Я немного поиграл с этим, и (как я подозревал) примерно 95% стоимости этой программы (тестирование с помощью фида с 25 элементами в Blogger) покрывается вызовами 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)

И, повторюсь, это не даст вам существенного улучшения производительности, но код гораздо более выразителен, чем вы действительно пытаетесь сделать, и, следовательно, намного легче поддерживать.

...