Часто задаваемые вопросы по LINQ

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

Являются ли они хорошими централизованными хранилищами информации или книг для «Эффективного LINQ»? В противном случае, какова ваша личная любимая высокопроизводительная технология LINQ?

В первую очередь я связан с LINQ to Objects, но все предложения по LINQ to SQL и LINQ to XML также приветствуются, конечно. Благодарю.

Простое понимание того, что LINQ делает внутри, должно давать достаточную информацию, чтобы знать, принимаете ли вы производительность.

Вот простой пример, где LINQ помогает повысить производительность. Рассмотрим этот типичный подход старой школы:

 List foos = GetSomeFoos(); List filteredFoos = new List(); foreach(Foo foo in foos) { if(foo.SomeProperty == "somevalue") { filteredFoos.Add(foo); } } myRepeater.DataSource = filteredFoos; myRepeater.DataBind(); 

Таким образом, вышеприведенный код будет дважды итератировать и выделить второй контейнер для хранения отфильтрованных значений. Какая трата! Сравнить с:

 var foos = GetSomeFoos(); var filteredFoos = foos.Where(foo => foo.SomeProperty == "somevalue"); myRepeater.DataSource = filteredFoos; myRepeater.DataBind(); 

Это повторяется только один раз (когда ретранслятор связан); он только когда-либо использует оригинальный контейнер; filteredFoos – это просто промежуточный перечислитель. И если по какой-то причине вы решили не связывать ретранслятор позже, ничего не пропадает. Вы даже не повторяете и не оцениваете один раз.

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

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

В первую очередь, Linq не волшебным образом сохраняет вашу программу время или память, необходимые для выполнения операции; это просто может задержать эти операции до полной необходимости. OrderBy () выполняет QuickSort, который займет время nlogn точно так же, как если бы вы написали свой собственный QuickSorter или использовали List.Sort () в нужное время. Поэтому всегда помните о том, что вы просите Linq делать в серии при написании запросов; если манипуляция не нужна, попробуйте реструктурировать цепочку запросов или методов, чтобы избежать ее.

Точно так же определенные операции (сортировка, группировка, агрегаты) требуют знания всего набора, на который они действуют. Последний элемент в серии может быть первым, который операция должна вернуть из своего iteratorа. Кроме того, поскольку операции Linq не должны изменять исходный список, но многие из используемых им алгоритмов (т. Е. На месте сортировки), эти операции заканчиваются не только оценкой, но и копированием всего перечислимого в конкретную конечную структуру , выполняя операцию и уступая ей. Итак, когда вы используете OrderBy () в инструкции, и вы запрашиваете элемент из конечного результата, все, что предоставленный ему IEnumerable может выдавать, оценивается, сохраняется в памяти как массив, сортируется, а затем возвращается один элемент в время. Мораль заключается в том, что любая операция, которая требует конечного набора вместо перечислимого, должна быть помещена как можно ближе к запросу, позволяя другим операциям, таким как Where () и Select (), уменьшить мощность и размер памяти исходного набора.

Наконец, методы Linq значительно увеличивают размер стека вызовов и объем памяти вашей системы. Каждая операция, которая должна знать весь набор, сохраняет весь источник в памяти до тех пор, пока последний элемент не будет итерирован, а оценка каждого элемента будет включать стек вызовов, по крайней мере, вдвое превышающий количество методов в вашей цепочке или предложениях в вашем встроенном заявлении (вызов для каждого Moveter () или его GetEnumerator каждого iteratorа плюс, по крайней мере, один вызов каждой lambda в пути). Это просто приведет к большему, более медленному алгоритму, чем интеллектуально спроектированный встроенный алгоритм, который выполняет те же манипуляции. Основным преимуществом Linq является простота кода. Создание, а затем сортировка, словарь списков значений групп не очень легкий для понимания код (поверьте мне). Микрооптимизация может запутать его дальше. Если производительность является вашей основной задачей, то не используйте Linq; он добавит примерно 10% накладных расходов и в несколько раз превысит накладные расходы на управление списком на месте. Тем не менее, ремонтопригодность обычно является основной задачей разработчиков, и Linq DEFINITELY помогает там.

Что касается производительности: если производительность вашего алгоритма является священным, непримиримым первым приоритетом, вы будете программировать на неуправляемом языке, таком как C ++; .NET будет намного медленнее, поскольку он является управляемой средой выполнения, с встроенной компиляцией JIT, управляемой памятью и дополнительными системными streamами. Я бы принял философию, что она «достаточно хороша»; Linq может вводить замедление по своей природе, но если вы не можете отличить это, и ваш клиент не может отличить эту информацию, то для всех практических целей нет никакой разницы. «Преждевременная оптимизация – это корень всего зла»; Заставьте это работать, ТОГДА ищите возможности сделать его более совершенным, пока вы и ваш клиент не согласитесь, что он достаточно хорош. Он всегда может быть «лучше», но если вы не хотите быть машинным кодом для ручной упаковки, вы найдете точку, которая меньше, чем вы можете объявить победу и двигаться дальше.

Существуют различные факторы, которые влияют на производительность.

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

С точки зрения абсолютной эффективности, работая с предопределенными хранимыми процедурами, вы можете увидеть некоторый рост производительности, но в целом подход к разработке заключается в разработке решения с использованием системы, предлагающей разумную производительность (например, LINQ), и не беспокоиться о нескольких процентных потерях производительности. Если запрос выполняется медленно, возможно, вы посмотрите на оптимизацию.

Реальность такова, что большинство запросов не будет иметь ни малейшей проблемы с выполнением LINQ. Другой факт заключается в том, что если ваш запрос работает медленно, скорее всего, это проблемы с индексацией, структурой и т. Д., Чем с самим запросом, поэтому даже если вы хотите оптимизировать вещи, вы часто не будете касаться LINQ, структура базы данных, с которой она работает.

Для обработки XML, если у вас есть документ, который загружается и анализируется в памяти (например, что-либо на основе модели DOM или XmlDocument или что-то еще), тогда вы получите больше использования памяти, чем системы, которые делают что-то вроде поднятия событий на указывают на обнаружение начального или конечного тега, но не на создание полной версии документа (например, SAX или XmlReader). Недостатком является то, что обработка на основе событий, как правило, является более сложной. Опять же, с большинством документов проблем не будет: в большинстве систем имеется несколько ГБ ОЗУ, поэтому рассмотрение нескольких МБ, представляющих один XML-документ, не является проблемой (и вы часто обрабатываете большой набор XML-документов, по крайней мере, несколько последовательно). Это только если у вас есть огромный XML-файл, который займет 100-е МБ, что вы беспокоитесь о конкретном выборе.

Имейте в виду, что LINQ позволяет вам перебирать списки в памяти и т. Д., Поэтому в некоторых ситуациях (например, когда вы собираетесь использовать набор результатов снова и снова в функции), вы можете использовать .ToList или .ToArray, чтобы вернуть результаты. Иногда это может быть полезно, хотя обычно вы пытаетесь использовать запрос базы данных, а не в памяти.

Что касается личных фаворитов – NHibernate LINQ – это инструмент объектно-реляционного сопоставления, который позволяет вам определять classы, определять детали отображения, а затем получать его для генерации базы данных из ваших classов, а не наоборот, а поддержка LINQ довольно хорошо (конечно, лучше, чем у SubSonic).

В linq to SQL вам не нужно заботиться о производительности. вы можете связать все ваши заявления так, как вы считаете, это наиболее читаемые. Linq просто преобразует все ваши заявления в один оператор SQL в конце, который только вызывается / выполняется в конце (например, когда вы вызываете .ToList()

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

Существует проект codeplex под названием i4o, который я использовал некоторое время назад, что может помочь улучшить производительность Linq для объектов в тех случаях, когда вы выполняете сравнения сравнений, например

 from p in People where p.Age == 21 select p; 

http://i4o.codeplex.com/ Я не тестировал его с .Net 4, поэтому не могу сказать, что он все равно будет работать, но стоит проверить. Чтобы заставить его работать над своей магией, вам в основном просто нужно украсить свой class некоторыми атрибутами, чтобы указать, какое свойство следует индексировать. Когда я использовал его, прежде чем он работает только с сравнением равенства.

Interesting Posts

Как изменить каталог данных MySQL?

Получение контекста сервлетов, сеанса и запроса в внешнем контейнере POJO

Ошибка раздувания classа и файла android.support.v7.widget.CardView

Относительная производительность std :: vector vs. std :: list vs. std :: slist?

В Perl существует встроенный способ сравнения двух массивов для равенства?

инициировать событие при изменении контента

создание параметризованных представлений в oracle11g

Ярлык для манипуляции с текущим URL-адресом

R: Пользовательская легенда для многослойного ggplot

Как осуществить первый проход?

Обновление до Chrome 36, черный экран, отсутствие адресной строки, невозможно удалить

Невозможно включить заголовки C ++, такие как вектор в Android NDK

Есть ли горячая клавиша Windows или ярлык для переключения на определенный экран?

Мониторинг температуры на Dell Precision M4500 под Linux: обнаружение датчиков не означает, что дальше?

В чем разница между ContentControl и ContentPresenter?

Давайте будем гением компьютера.