LINQ и производительность

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

Очень распространённая задача - работа с двумя массивами, просто нюансы бывают разные. Допустим, что есть два массива данных - пользователей сайта и их адреса. У вас есть все данные, просто нужно взять, и добавить адреса всем пользователям. Возможно помимо этого нужно выполнить что-то еще и в таких случаях я уже не раз видел код в виде: 

List addresses = . . . ;

List employees = . . . ;

 

foreach (EmployeeModel employee in employees) {

  // Здесь могуть быть какие-то вычисления

  employee.Addresses = addresses.Where(m => m.EmployeeId == employee.EmployeeId);

}

Благодаря LINQ такой код легко написать и он легко читается. Но если в списке адресов и в списке пользоватлей большое количество данных, то для каждого пользователя будет происходить сканирование всех строк в адресах. Этот код просто пиздец процессору.

Вариантов решения подобных вещей несколько, уверен, что и ты придумаешь что-нибудь. Самый банальный, который может прийти - сначала создать цикл и пройтись по всем адресам и создать хэш таблицу или словарь, где ключем будет EmployeeID, а элементом список всех его адресов, а потом пройтись по всем employee и использовать этот словарь или таблицу. Это просто даже без знания патернов или алгоритмов самое банальное решение проблемы. 

Это не единственный случай, когда LINQ используется неэффективно. Бывают случаи, когда метод доступа к базе данных возвращает IEnumerable. Отличная идея - метод просто вернет этот список без реального доступа к базе и если никто этот список не тронет, то и к базе обращения не будет. А если этот список тронуть 10 раз? Будет 10 обращений к базе. Опять же, если в предыдущем примере addresses превратить в IEnumerable, то на каждом этапе цикла будет обращение к базе в поисках всех адресов. Упс. 

Если у тебя есть  IEnumerable и к нему придется обращаться несколько раз, не поленись привести его в список - выполни ToList()


Понравилось? Кликни Лайк, чтобы я знал, какой контент более интересен читателям. Заметку пока еще никто не лайкал и ты можешь быть первым


Комментарии

XCode

13 Мая 2016

/IMHO: Плюсом, добавил бы использования for а не foreach.


Ololo

13 Мая 2016

Разница между for и foreach смешная в данном случае, с таким успехом можно убрать linq и сделать все через вложенные for.


Михаил Фленов

13 Мая 2016

Ну Linq слишком просто для написания циклов и в документации написано, что он компилирует и оптимизируется, поэтому видимо народ думает, что в таком патерне будет какая-то магия. Не будет магии, будет жопа.


Добавить Комментарий

Еще что-нибудь

Хотите найти еще что-то интересное почитать? Можно попробовать отфильтровать заметки на блоге по категориям.

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне