Производительность Linq при расчете двух списков с использованием внутреннего Contains - PullRequest
0 голосов
/ 24 мая 2018

РЕДАКТИРОВАТЬ 01 : Кажется, я нашел решение (нажмите для ответа) , которое работает для меня.Переход от и часов к простым секундам с помощью предварительного вычисления , а затем с применением метода расширения .Except() ;но оставьте это открытым, если кто-то еще столкнется с этой проблемой или , если кто-то найдет лучшее решение .


ОРИГИНАЛЬНЫЙ ВОПРОС

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

Я получаю все данные в памяти, а затем, например, выполняю этот запрос, где я ищу объектыкоторые больше не существуют в исходной системе, но присутствуют в промежуточной базе данных - и, следовательно, должны быть помечены как «удаленные».Узкое место - это первая часть запроса LINQ - на .Contains(), как я могу улучшить его производительность - может, с .Except(), с помощью специального компаратора?Или мне лучше всего поместить их в список хеширования, и они будут выполнять сравнение?

Проблема в том, что мне нужно иметь подготовленные объекты впоследствии, чтобы выполнить некоторые преобразования свойств на них, это казалось самым простым решением, но, к сожалению,это очень медленно на объектах 20k

stagedSystemObjects.Where(stagedSystemObject => 
   !sourceSystemObjects.Select(sourceSystemObject => sourceSystemObject.Code)
        .Contains(stagedSystemObject.Code)
   )
   .Select(x =>
   {
       x.ActiveStatus = ActiveStatuses.Disabled;
       x.ChangeReason = ChangeReasons.Edited;
       return x;
   })
  .ToList();

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

На основании ответа Ива Шелпе.Я сделал небольшие изменения, чтобы сделать это быстрее.Основная идея - отменить первые два ToList и использовать PLINQ.Посмотрите, поможет ли эта справка

            var stagedSystemCodes = stagedSystemObjects.Select(x => x.Code);
            var sourceSystemCodes = sourceSystemObjects.Select(x => x.Code);
            var codesThatNoLongerExistInSourceSystem = stagedSystemCodes.Except(sourceSystemCodes).ToArray();

            var y = stagedSystemObjects.AsParallel()
               .Where(stagedSystemObject =>
                    codesThatNoLongerExistInSourceSystem.Contains(stagedSystemObject.Code))                  
               .Select(x =>
               {
                   x.ActiveStatus = ActiveStatuses.Disabled;
                   x.ChangeReason = ChangeReasons.Edited;
                   return x;
               }).ToArray();

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

0 голосов
/ 24 мая 2018

Я нашел решение для этой проблемы - которое сократило его до нескольких секунд вместо 200кб объектов.

Это делается путем предварительного вычисления , а затем с применением метода расширения .Except()

Так что больше не "цепочка""linq-запросы или выполнение .Contains внутри метода ... но сделать его" более простым ", сначала проецируя оба на список string s, так что внутренний расчет не должен повторяться снова и снова вПример кода оригинального вопроса.

Вот мое решение, которое пока удовлетворительно.Однако я оставляю это открытым, если кто-нибудь придумает изысканное / лучшее решение!

var stagedSystemCodes = stagedSystemObjects.Select(x => x.Code).ToList();
var sourceSystemCodes = sourceSystemObjects.Select(x => x.Code).ToList();
var codesThatNoLongerExistInSourceSystem = stagedSystemCodes.Except(sourceSystemCodes).ToList();

return stagedSystemObjects
   .Where(stagedSystemObject => 
        codesThatNoLongerExistInSourceSystem.Contains(stagedSystemObject.Code))
   .Select(x =>
   {
       x.ActiveStatus = ActiveStatuses.Disabled;
       x.ChangeReason = ChangeReasons.Edited;
       return x;
   })
   .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...