Denis Kaminsky
Denis Kaminsky

Reputation: 139

How .First() calls will impact the performance?

var result = users
.Where(x => x.IsActive)
.GroupBy(x => x.City)
.Select(x => new MyModel 
{
    Name = x.First().Name,
    Age = x.First(),
    CreatingDate = x.First().CreationDate,
    HairColor = x.First().HairColor
})
.ToArray();

How many times will the x.First() method be called for each group? Does this mean that the method will be called 4 times for each group. Or is there an optimization that fetches an element once using a x.First() method, then saves it to a variable and uses the variable to retrieve the fields?

Upvotes: 0

Views: 125

Answers (3)

M. Akar
M. Akar

Reputation: 1865

The .First() will be called 4 times. However, as @JonasH said, it is O(1) time so it shouldn't be too bad.

Still, though I think you should put it as a variable. You can use statement lambda instead of expression lambda as follows;

var result = users
    .Where(x => x.IsActive)
    .GroupBy(x => x.City)
    .Select(x =>
    {
        var first = x.First();
        return new MyModel
        {
            Name = first.Name,
            Age = first.Age,
            CreatingDate = first.CreationDate,
            HairColor = first.HairColor
        };
    })
    .ToArray();

This way you can use functions more complex than O(1).

Upvotes: 1

Dialecticus
Dialecticus

Reputation: 16761

JonasH gave an answer to your question, but if you want the answer to the question "how can I avoid multiple First calls" then check this code out:

var result = users
.Where(x => x.IsActive)
.GroupBy(x => x.City)
.Select(x => new { Key = x.Key, First = x.First() })
.Select(x => new MyModel 
{
    Name = x.First.Name,
    Age = x.First.Age, // I assume there's a typo here in your code
    CreatingDate = x.First.CreationDate,
    HairColor = x.First.HairColor
})
.ToArray();

Upvotes: 1

JonasH
JonasH

Reputation: 36351

How many times will the x.First() method be called for each group?

4

Does this mean that the method will be called 4 times for each group

Yes

Or is there an optimization that fetches an element once using a x.First() method, then saves it to a variable and uses the variable to retrieve the fields?

No, you would have to do that yourself. For this to be done the jitter would need to prove that the result are the same for each call. While this would be possible, it would be complicated and expensive to do, so the jitter most likely will not bother.

However, .First() should be a constant time function, so the overhead is much less than for example .Last(). But if you are more concerned about performance than readability you should probably avoid linq altogether, since the abstraction level Linq provides does have some overhead.

And if you are concerned about performance, measure! We might make educated guesses about performance, but the only way to be sure is to benchmark the code.

Upvotes: 0

Related Questions