Converting IEnumerable <T> to List <T> in LINQ result, huge performance loss

On LINQ result, you like this:

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

      

However ToList<T>

really slow, does it make the list volatile and hence the conversion slow?

Most of the time I can just have my own IEnumerable

or Paralell.DistinctQuery

but now I want to bind the items to the DataGridView, so I need some other way than IEnumerable

, suggestions on how I would improve the performance in ToList or any other replacement?

For 10 million entries, it IEnumerable

.ToList<T>

takes about 6 seconds.

+1


source to share


4 answers


.ToList()

slower compared to what?

If you compare

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

      



to

var result = from x in Items select x;

      

you should notice that since the query is being evaluated lazily, the first line does nothing at all. It doesn't retrieve any records. The delayed execution makes this comparison completely unfair.

+10


source


This is because LINQ likes to be lazy and do as little work as possible. This line:

var result = from x in Items select x;

      

despite your choice of name, not really the result, it's just the request object. It doesn't retrieve any data.



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

      

Now you have actually requested the result, so it should fetch the data from the source and make a copy of it. ToList makes sure a copy is made.

With this in mind, it is hardly surprising that the second line is much slower than the first.

+7


source


No, it doesn't create a list that takes time, it retrieves data that takes time.

Your first line of code doesn't actually retrieve data, it only sets an IEnumerable capable of retrieving data. This is when you call the ToList method that will actually get all the data, which is why the entire execution time is on the second line.

You should also consider using ten million lines in a grid. No user will view all rows, so there really is no point in getting them. Perhaps you should suggest a way to filter the result before getting any data.

+2


source


I think this is due to memory reallocation: ToList

cannot know in advance the size of the collection so that it can allocate enough space to store all the elements. Therefore, it must redistribute List<T>

as it grows.

If you can estimate the size of your result set, it will be much faster to preset enough items with a constructor overload List<T>(int)

and then manually add items to it.

0


source







All Articles