1

In several projects I am using the mapping functions of AutoMapper. I will use the object Car as an example through the full question.

First my set-up:

I define my maps with profiles:

public class CarProfile : Profile
{
    public CarProfile()
    {
        CreateMap<Car, CarResponse>();
    }
}

I initialize AutoMapper in ASP.NET Core Web API with:

services.AddAutoMapper();

Using the NuGet packages AutoMapper and AutoMapper.Extensions.Microsoft.DependencyInjection

The mapper is automically injected in the constructor and set as a private field _mapper.

Eventually I map a collection with the following piece of code:

_mapper.Map<IEnumerable<Car>, IEnumerable<CarResponse>>(_context.Cars);

It's also worth to mention that _context.Cars is in this case an DbSet<T>.

Now my actual question is: would it be different if I would use an array instead of a IEnumerable.

Example given:

_mapper.Map<Car[], CarResponse[]>(_context.Cars);

Please consider performance, clean code and behavioural differences.

Nick N.
  • 12,902
  • 7
  • 57
  • 75
  • 4
    Why wouldn't you measure performance yourself? (https://ericlippert.com/2012/12/17/performance-rant/) – Darjan Bogdan Oct 11 '17 at 13:48
  • 1
    Good point, will do. If however anyone knows please still answer. – Nick N. Oct 11 '17 at 13:52
  • 1
    I doubt the collection type will matter nearly as much as the complexity of the object graph being mapped. Doing bulk mappings is slow regardless of using `Array` or `IEnumerable` – DiskJunky Oct 11 '17 at 13:57
  • 1
    One thing to consider - is Automapper smart enough to map things one at a time, so for instance if the `Car`s were coming from a streaming source (a DB for example), it could map them as they're enumerated, rather than mapping the whole collection. I've not used it enough to know - may be worth looking in to. – James Thorpe Oct 11 '17 at 13:58
  • I agree that the difference may be irrelevant, but I am still interested in the outcome :) – Nick N. Oct 11 '17 at 14:05
  • Check [the execution plan](https://github.com/AutoMapper/AutoMapper/wiki/Understanding-your-mapping). – Lucian Bargaoanu Oct 11 '17 at 15:04
  • @LucianBargaoanu Do you have any resources on how to utilize this execution plan? I have generated it, but can't really get the information I am looking for out of them. – Nick N. Oct 11 '17 at 19:57
  • As that link explains, you get what gets executed. At this point, it's just C# code. That's all the information you need. – Lucian Bargaoanu Oct 11 '17 at 20:13
  • Any ideas on what I can do to edit this question so that it is not too broad and still valuable for the community? Or would it be better to close? – Nick N. Oct 11 '17 at 21:20
  • Closing would be best. – Lucian Bargaoanu Oct 12 '17 at 09:51

1 Answers1

1

Behavioural differences

I generated the execution plan and I can conclude that there at least is a difference. See this link for my comparison: https://www.diffnow.com/?report=elujt . Analyzing the C# code makes clear that there happens more when using an array.

Performance

Since this still does not give any insights in performance, I measured that using Stopwatch.

        var watchienumerable = Stopwatch.StartNew();
        var ienumerable = _mapper.Map<IEnumerable<Car>, IEnumerable<CarResponse>>(contextDevices);
        watchienumerable.Stop();

Measuring IEnumerable first:

  • IEnumerable: 21 milliseconds;
  • Array: 7 milliseconds;

Measuring Array first:

  • IEnumerable: 7 milliseconds;
  • Array: 21 milliseconds;

These results are not representative, because the mapper still needs to be warmed up.

Mapping a collection related to this object first (to warm up the mapping, initialize caching etc.)

  • IEnumerable: 57704 ticks;
  • Array: 122014 ticks;

I can conclude that mapping to an IEnumerable from (something that is not an array) is faster than mapping to an array. With hindsight, it sounds quite obvious.

When the input is an array:

  • IEnumerable: 18642 ticks;
  • Array: 1392 ticks;

It's also worth to mention that if use the actual type of _context.Cars which is DbSet<Car>. It is exactly as fast as when I use IEnumerable<Car>.

Word of advice: I would use the type that is closest to the input and still matches your desired output. In my case, I will stick to using IEnumerable.

Clean code

This part of my answer is highly opiniated and very open to comments. But I think Car[] reads better than IEnumerable<Car>.

However since there are behavioural and performance differences I don't think it's clean to use an array here. It also changes the intent. So using IEnumerable<T> would be better.

Nick N.
  • 12,902
  • 7
  • 57
  • 75