Преобразование IEnumberable <T>в список <T>по результату LINQ, огромная потеря производительности - PullRequest
1 голос
/ 29 января 2010

На LINQ-результате вам понравится:

var result = from x in Items select x;
List<T> list = result.ToList<T>();

Однако, ToList<T> действительно медленный, делает ли его список изменчивым и, следовательно, преобразование медленное?

В большинстве случаев мне удается просто иметь свой IEnumerable или как Paralell.DistinctQuery, но теперь я хочу связать элементы с DataGridView, поэтому мне нужно как-то иначе, чем IEnumerable, предложения о том, как я заработает на ToList или на любой замене?

На 10 миллионных записях в IEnumerable, .ToList<T> занимает около 6 секунд.

Ответы [ 4 ]

10 голосов
/ 29 января 2010

.ToList() медленный по сравнению с чем ?

Если вы сравниваете

var result = from x in Items select x;
List<T> list = result.ToList<T>();

до

var result = from x in Items select x;

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

7 голосов
/ 29 января 2010

Это потому, что LINQ любит быть ленивым и выполнять как можно меньше работы. Эта строка:

var result = from x in Items select x;

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

List<T> list = result.ToList<T>();

Теперь вы фактически запросили результат, поэтому он должен извлечь данные из источника и сделать их копию. ToList гарантирует, что копия сделана.

Учитывая это, неудивительно, что вторая строка намного медленнее первой.

2 голосов
/ 29 января 2010

Нет, это не создание списка, который требует времени, это выборка данных, которые требуют времени.

Ваша первая строка кода на самом деле не извлекает данные, она только устанавливает IEnumerable, который способен извлекать данные. Когда вы вызываете метод ToList, он на самом деле получает все данные, и поэтому все время выполнения находится во второй строке.

Вам также следует подумать, полезно ли вообще иметь десять миллионов строк в сетке. Ни один пользователь никогда не будет просматривать все строки, так что нет смысла получать их все. Возможно, вам следует предложить способ фильтрации результатов, прежде чем получать какие-либо данные.

0 голосов
/ 29 января 2010

Я думаю, что это из-за перераспределения памяти: ToList не может заранее знать размер коллекции, чтобы она могла выделить достаточно места для хранения всех элементов. Следовательно, он должен перераспределить List<T> по мере роста.

Если вы сможете оценить размер вашего набора результатов, будет гораздо быстрее предварительно выделить достаточно элементов с помощью перегрузки конструктора List<T>(int), а затем вручную добавить в него элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...