feat: Introduce object mapper benchmarking project
This project provides a comparative analysis of popular .NET object-to-object mapping libraries, including AutoMapper, TinyMapper, Mapster, and Mapperly, against a hand-written and a generated manual mapper. It uses BenchmarkDotNet to measure performance and memory allocation when mapping a complex Spotify album DTO structure.
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.33516.290
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MappersBenchmarks", "MappersBenchmarks\MappersBenchmarks.csproj", "{D9BBFC12-AE56-4065-8CCE-CC6E7549690B}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{D9BBFC12-AE56-4065-8CCE-CC6E7549690B}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D9BBFC12-AE56-4065-8CCE-CC6E7549690B}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D9BBFC12-AE56-4065-8CCE-CC6E7549690B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D9BBFC12-AE56-4065-8CCE-CC6E7549690B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {3771561C-97D9-4E09-96A2-141DE855B85D}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Order;
|
||||||
|
using MappersBenchmarks.Models;
|
||||||
|
using Mapster;
|
||||||
|
|
||||||
|
namespace MappersBenchmarks;
|
||||||
|
|
||||||
|
[MemoryDiagnoser(false)]
|
||||||
|
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||||
|
public class Benchmarks
|
||||||
|
{
|
||||||
|
private readonly SpotifyAlbumDto _spotifyAlbumDto = TestData.ExampleAlbum;
|
||||||
|
private readonly IMapper _autoMapper;
|
||||||
|
private readonly MapperlyMapper _mapperlyMapper;
|
||||||
|
|
||||||
|
public Benchmarks()
|
||||||
|
{
|
||||||
|
//Automapper Configuration
|
||||||
|
var mapperConfig = new MapperConfiguration(cfg =>
|
||||||
|
{
|
||||||
|
cfg.CreateMap<SpotifyAlbumDto, SpotifyAlbum>();
|
||||||
|
cfg.CreateMap<CopyrightDto, Copyright>();
|
||||||
|
cfg.CreateMap<ArtistDto, Artist>();
|
||||||
|
cfg.CreateMap<ExternalIdsDto, ExternalIds>();
|
||||||
|
cfg.CreateMap<ExternalUrlsDto, ExternalUrls>();
|
||||||
|
cfg.CreateMap<TracksDto, Tracks>();
|
||||||
|
cfg.CreateMap<ImageDto, Image>();
|
||||||
|
cfg.CreateMap<ItemDto, Item>();
|
||||||
|
cfg.CreateMap<SpotifyAlbum, SpotifyAlbumDto>();
|
||||||
|
cfg.CreateMap<Copyright, CopyrightDto>();
|
||||||
|
cfg.CreateMap<Artist, ArtistDto>();
|
||||||
|
cfg.CreateMap<ExternalIds, ExternalIdsDto>();
|
||||||
|
cfg.CreateMap<ExternalUrls, ExternalUrlsDto>();
|
||||||
|
cfg.CreateMap<Tracks, TracksDto>();
|
||||||
|
cfg.CreateMap<Image, ImageDto>();
|
||||||
|
cfg.CreateMap<Item, ItemDto>();
|
||||||
|
});
|
||||||
|
_autoMapper = mapperConfig.CreateMapper();
|
||||||
|
|
||||||
|
//TinyMapper Configuration
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<SpotifyAlbumDto, SpotifyAlbum>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<CopyrightDto, Copyright>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ArtistDto, Artist>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ExternalIdsDto, ExternalIds>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ExternalUrlsDto, ExternalUrls>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<TracksDto, Tracks>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ImageDto, Image>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ItemDto, Item>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<SpotifyAlbum, SpotifyAlbumDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<Copyright, CopyrightDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<Artist, ArtistDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ExternalIds, ExternalIdsDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<ExternalUrls, ExternalUrlsDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<Tracks, TracksDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<Image, ImageDto>();
|
||||||
|
Nelibur.ObjectMapper.TinyMapper.Bind<Item, ItemDto>();
|
||||||
|
|
||||||
|
// Mapperly
|
||||||
|
_mapperlyMapper = new MapperlyMapper();
|
||||||
|
|
||||||
|
//Mapster don't need configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum AutoMapper()
|
||||||
|
{
|
||||||
|
return _autoMapper.Map<SpotifyAlbum>(_spotifyAlbumDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum TinyMapper()
|
||||||
|
{
|
||||||
|
return Nelibur.ObjectMapper.TinyMapper.Map<SpotifyAlbum>(_spotifyAlbumDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum Mapster()
|
||||||
|
{
|
||||||
|
return _spotifyAlbumDto.Adapt<SpotifyAlbum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum Mapperly()
|
||||||
|
{
|
||||||
|
return _mapperlyMapper.Map(_spotifyAlbumDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum MappingGenerator()
|
||||||
|
{
|
||||||
|
return _spotifyAlbumDto.Generated_Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public SpotifyAlbum ManualMapper()
|
||||||
|
{
|
||||||
|
return _spotifyAlbumDto.My_Map();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
using MappersBenchmarks.Models;
|
||||||
|
|
||||||
|
namespace MappersBenchmarks;
|
||||||
|
|
||||||
|
public static class MappingGeneratorMapper
|
||||||
|
{
|
||||||
|
public static SpotifyAlbum Generated_Map(this SpotifyAlbumDto spotifyAlbumDto)
|
||||||
|
{
|
||||||
|
return new SpotifyAlbum
|
||||||
|
{
|
||||||
|
AlbumType = spotifyAlbumDto.AlbumType,
|
||||||
|
Artists = spotifyAlbumDto.Artists.Select(spotifyAlbumDtoArtist => new Artist
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = spotifyAlbumDtoArtist.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Href = spotifyAlbumDtoArtist.Href,
|
||||||
|
Id = spotifyAlbumDtoArtist.Id,
|
||||||
|
Name = spotifyAlbumDtoArtist.Name,
|
||||||
|
Type = spotifyAlbumDtoArtist.Type,
|
||||||
|
Uri = spotifyAlbumDtoArtist.Uri
|
||||||
|
}).ToArray(),
|
||||||
|
AvailableMarkets = spotifyAlbumDto.AvailableMarkets,
|
||||||
|
Copyrights = spotifyAlbumDto.Copyrights.Select(spotifyAlbumDtoCopyright => new Copyright
|
||||||
|
{
|
||||||
|
Text = spotifyAlbumDtoCopyright.Text,
|
||||||
|
Type = spotifyAlbumDtoCopyright.Type
|
||||||
|
}).ToArray(),
|
||||||
|
ExternalIds = new ExternalIds
|
||||||
|
{
|
||||||
|
Upc = spotifyAlbumDto.ExternalIds.Upc
|
||||||
|
},
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = spotifyAlbumDto.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Genres = spotifyAlbumDto.Genres,
|
||||||
|
Href = spotifyAlbumDto.Href,
|
||||||
|
Id = spotifyAlbumDto.Id,
|
||||||
|
Images = spotifyAlbumDto.Images.Select(spotifyAlbumDtoImage => new Image
|
||||||
|
{
|
||||||
|
Height = spotifyAlbumDtoImage.Height,
|
||||||
|
Url = spotifyAlbumDtoImage.Url,
|
||||||
|
Width = spotifyAlbumDtoImage.Width
|
||||||
|
}).ToArray(),
|
||||||
|
Name = spotifyAlbumDto.Name,
|
||||||
|
Popularity = spotifyAlbumDto.Popularity,
|
||||||
|
ReleaseDate = spotifyAlbumDto.ReleaseDate,
|
||||||
|
ReleaseDatePrecision = spotifyAlbumDto.ReleaseDatePrecision,
|
||||||
|
Tracks = new Tracks
|
||||||
|
{
|
||||||
|
Href = spotifyAlbumDto.Tracks.Href,
|
||||||
|
Items = spotifyAlbumDto.Tracks.Items.Select(spotifyAlbumDtoTracksItem => new Item
|
||||||
|
{
|
||||||
|
Artists = spotifyAlbumDtoTracksItem.Artists.Select(spotifyAlbumDtoTracksItemArtist => new Artist
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = spotifyAlbumDtoTracksItemArtist.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Href = spotifyAlbumDtoTracksItemArtist.Href,
|
||||||
|
Id = spotifyAlbumDtoTracksItemArtist.Id,
|
||||||
|
Name = spotifyAlbumDtoTracksItemArtist.Name,
|
||||||
|
Type = spotifyAlbumDtoTracksItemArtist.Type,
|
||||||
|
Uri = spotifyAlbumDtoTracksItemArtist.Uri
|
||||||
|
}).ToArray(),
|
||||||
|
AvailableMarkets = spotifyAlbumDtoTracksItem.AvailableMarkets,
|
||||||
|
DiscNumber = spotifyAlbumDtoTracksItem.DiscNumber,
|
||||||
|
DurationMs = spotifyAlbumDtoTracksItem.DurationMs,
|
||||||
|
Explicit = spotifyAlbumDtoTracksItem.Explicit,
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = spotifyAlbumDtoTracksItem.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Href = spotifyAlbumDtoTracksItem.Href,
|
||||||
|
Id = spotifyAlbumDtoTracksItem.Id,
|
||||||
|
Name = spotifyAlbumDtoTracksItem.Name,
|
||||||
|
PreviewUrl = spotifyAlbumDtoTracksItem.PreviewUrl,
|
||||||
|
TrackNumber = spotifyAlbumDtoTracksItem.TrackNumber,
|
||||||
|
Type = spotifyAlbumDtoTracksItem.Type,
|
||||||
|
Uri = spotifyAlbumDtoTracksItem.Uri
|
||||||
|
}).ToArray(),
|
||||||
|
Limit = spotifyAlbumDto.Tracks.Limit,
|
||||||
|
Next = spotifyAlbumDto.Tracks.Next,
|
||||||
|
Offset = spotifyAlbumDto.Tracks.Offset,
|
||||||
|
Previous = spotifyAlbumDto.Tracks.Previous,
|
||||||
|
Total = spotifyAlbumDto.Tracks.Total
|
||||||
|
},
|
||||||
|
Type = spotifyAlbumDto.Type,
|
||||||
|
Uri = spotifyAlbumDto.Uri
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpotifyAlbum My_Map(this SpotifyAlbumDto spotifyAlbumDto)
|
||||||
|
{
|
||||||
|
var result = new SpotifyAlbum
|
||||||
|
{
|
||||||
|
AlbumType = spotifyAlbumDto.AlbumType,
|
||||||
|
AvailableMarkets = spotifyAlbumDto.AvailableMarkets,
|
||||||
|
ExternalIds = new ExternalIds
|
||||||
|
{
|
||||||
|
Upc = spotifyAlbumDto.ExternalIds.Upc
|
||||||
|
},
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = spotifyAlbumDto.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Genres = spotifyAlbumDto.Genres,
|
||||||
|
Href = spotifyAlbumDto.Href,
|
||||||
|
Id = spotifyAlbumDto.Id,
|
||||||
|
Name = spotifyAlbumDto.Name,
|
||||||
|
Popularity = spotifyAlbumDto.Popularity,
|
||||||
|
ReleaseDate = spotifyAlbumDto.ReleaseDate,
|
||||||
|
ReleaseDatePrecision = spotifyAlbumDto.ReleaseDatePrecision,
|
||||||
|
Type = spotifyAlbumDto.Type,
|
||||||
|
Uri = spotifyAlbumDto.Uri,
|
||||||
|
Artists = new Artist[spotifyAlbumDto.Artists.Length]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < spotifyAlbumDto.Artists.Length; i++)
|
||||||
|
{
|
||||||
|
var artistDto = spotifyAlbumDto.Artists[i];
|
||||||
|
result.Artists[i] = new Artist
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = artistDto.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Href = artistDto.Href,
|
||||||
|
Id = artistDto.Id,
|
||||||
|
Name = artistDto.Name,
|
||||||
|
Type = artistDto.Type,
|
||||||
|
Uri = artistDto.Uri
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Copyrights = new Copyright[spotifyAlbumDto.Copyrights.Length];
|
||||||
|
for (var i = 0; i < spotifyAlbumDto.Copyrights.Length; i++)
|
||||||
|
{
|
||||||
|
var copyrightDto = spotifyAlbumDto.Copyrights[i];
|
||||||
|
result.Copyrights[i] = new Copyright
|
||||||
|
{
|
||||||
|
Text = copyrightDto.Text,
|
||||||
|
Type = copyrightDto.Type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Images = new Image[spotifyAlbumDto.Images.Length];
|
||||||
|
for (var i = 0; i < spotifyAlbumDto.Images.Length; i++)
|
||||||
|
{
|
||||||
|
var imageDto = spotifyAlbumDto.Images[i];
|
||||||
|
result.Images[i] = new Image
|
||||||
|
{
|
||||||
|
Height = imageDto.Height,
|
||||||
|
Url = imageDto.Url,
|
||||||
|
Width = imageDto.Width
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Tracks = new Tracks
|
||||||
|
{
|
||||||
|
Href = spotifyAlbumDto.Tracks.Href,
|
||||||
|
Limit = spotifyAlbumDto.Tracks.Limit,
|
||||||
|
Next = spotifyAlbumDto.Tracks.Next,
|
||||||
|
Offset = spotifyAlbumDto.Tracks.Offset,
|
||||||
|
Previous = spotifyAlbumDto.Tracks.Previous,
|
||||||
|
Total = spotifyAlbumDto.Tracks.Total,
|
||||||
|
Items = new Item[spotifyAlbumDto.Tracks.Items.Length]
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < spotifyAlbumDto.Tracks.Items.Length; i++)
|
||||||
|
{
|
||||||
|
var itemDto = spotifyAlbumDto.Tracks.Items[i];
|
||||||
|
result.Tracks.Items[i] = new Item();
|
||||||
|
var item = result.Tracks.Items[i];
|
||||||
|
item.AvailableMarkets = itemDto.AvailableMarkets;
|
||||||
|
item.DiscNumber = itemDto.DiscNumber;
|
||||||
|
item.DurationMs = itemDto.DurationMs;
|
||||||
|
item.Explicit = itemDto.Explicit;
|
||||||
|
item.ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = itemDto.ExternalUrls.Spotify
|
||||||
|
};
|
||||||
|
item.Href = itemDto.Href;
|
||||||
|
item.Id = itemDto.Id;
|
||||||
|
item.Name = itemDto.Name;
|
||||||
|
item.PreviewUrl = itemDto.PreviewUrl;
|
||||||
|
item.TrackNumber = itemDto.TrackNumber;
|
||||||
|
item.Type = itemDto.Type;
|
||||||
|
item.Uri = itemDto.Uri;
|
||||||
|
|
||||||
|
item.Artists = new Artist[itemDto.Artists.Length];
|
||||||
|
for (var j = 0; j < itemDto.Artists.Length; j++)
|
||||||
|
{
|
||||||
|
var artistDto = itemDto.Artists[j];
|
||||||
|
item.Artists[i] = new Artist
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrls
|
||||||
|
{
|
||||||
|
Spotify = artistDto.ExternalUrls.Spotify
|
||||||
|
},
|
||||||
|
Href = artistDto.Href,
|
||||||
|
Id = artistDto.Id,
|
||||||
|
Name = artistDto.Name,
|
||||||
|
Type = artistDto.Type,
|
||||||
|
Uri = artistDto.Uri
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
using MappersBenchmarks.Models;
|
||||||
|
using Riok.Mapperly.Abstractions;
|
||||||
|
|
||||||
|
namespace MappersBenchmarks
|
||||||
|
{
|
||||||
|
[Mapper]
|
||||||
|
public partial class MapperlyMapper
|
||||||
|
{
|
||||||
|
|
||||||
|
public partial SpotifyAlbum Map(SpotifyAlbumDto spotifyAlbumDto);
|
||||||
|
|
||||||
|
//public partial SpotifyAlbum Map(SpotifyAlbumDto spotifyAlbum)
|
||||||
|
//{
|
||||||
|
// var newItem = new SpotifyAlbum()
|
||||||
|
// {
|
||||||
|
// AlbumType = spotifyAlbum.AlbumType,
|
||||||
|
// TotalTracks = spotifyAlbum.TotalTracks,
|
||||||
|
// AvailableMarkets = spotifyAlbum.AvailableMarkets,
|
||||||
|
// ExternalUrls = Map(spotifyAlbum.ExternalUrls),
|
||||||
|
// Href = spotifyAlbum.Href,
|
||||||
|
// Id = spotifyAlbum.Id,
|
||||||
|
// //Images = Map(spotifyAlbum.Images),
|
||||||
|
// Name = spotifyAlbum.Name,
|
||||||
|
// ReleaseDate = spotifyAlbum.ReleaseDate,
|
||||||
|
// ReleaseDatePrecision = spotifyAlbum.ReleaseDatePrecision,
|
||||||
|
// Restrictions = Map(spotifyAlbum.Restrictions),
|
||||||
|
// Type = spotifyAlbum.Type,
|
||||||
|
// Uri = spotifyAlbum.Uri,
|
||||||
|
// //Copyrights = Map(spotifyAlbum.Copyrights),
|
||||||
|
// //ExternalIds = Map(spotifyAlbum.ExternalIds),
|
||||||
|
// //Genres = Map(spotifyAlbum.Genres),
|
||||||
|
// Label = spotifyAlbum.Label,
|
||||||
|
// Popularity = spotifyAlbum.Popularity,
|
||||||
|
// //Artists = Map(spotifyAlbum.Artists),
|
||||||
|
// //Tracks = Map(spotifyAlbum.Tracks),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return newItem;
|
||||||
|
//}
|
||||||
|
|
||||||
|
/*
|
||||||
|
private partial List<string> Map(IList<string> source)
|
||||||
|
{
|
||||||
|
var destination = new List<string>();
|
||||||
|
|
||||||
|
if (source == null) return null;
|
||||||
|
|
||||||
|
foreach (var item in source)
|
||||||
|
{
|
||||||
|
destination.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial string[] Map(IList<string> source)
|
||||||
|
{
|
||||||
|
var destination = new List<string>();
|
||||||
|
|
||||||
|
if (source == null) return null;
|
||||||
|
|
||||||
|
foreach (var item in source)
|
||||||
|
{
|
||||||
|
destination.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial Image Map(ImageDto item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
|
||||||
|
var newItem = new Image()
|
||||||
|
{
|
||||||
|
Url = item.Url,
|
||||||
|
Height = item.Height,
|
||||||
|
Width = item.Width,
|
||||||
|
};
|
||||||
|
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial ExternalUrl Map(ExternalUrlDto item)
|
||||||
|
{
|
||||||
|
if (item == null) return default;
|
||||||
|
|
||||||
|
var newItem = new ExternalUrl()
|
||||||
|
{
|
||||||
|
Spotify = item.Spotify,
|
||||||
|
};
|
||||||
|
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial Restriction Map(RestrictionDto item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
|
||||||
|
var newItem = new Restriction()
|
||||||
|
{
|
||||||
|
Reason = item.Reason,
|
||||||
|
};
|
||||||
|
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial ExternalId Map(ExternalIdDto item)
|
||||||
|
{
|
||||||
|
if (item == null) return null;
|
||||||
|
|
||||||
|
var newItem = new ExternalId()
|
||||||
|
{
|
||||||
|
Isrc = item.Isrc,
|
||||||
|
Ean = item.Ean,
|
||||||
|
Upc = item.Upc,
|
||||||
|
};
|
||||||
|
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial List<string> Map(IEnumerable<string> source)
|
||||||
|
{
|
||||||
|
var destination = new List<string>();
|
||||||
|
|
||||||
|
if (source == null) return null;
|
||||||
|
|
||||||
|
foreach (var item in source)
|
||||||
|
{
|
||||||
|
destination.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AutoMapper" Version="12.0.1" />
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
|
||||||
|
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||||
|
<PackageReference Include="Riok.Mapperly" Version="2.7.0" />
|
||||||
|
<PackageReference Include="TinyMapper" Version="3.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
namespace MappersBenchmarks.Models;
|
||||||
|
|
||||||
|
public class SpotifyAlbum
|
||||||
|
{
|
||||||
|
public string AlbumType { get; set; }
|
||||||
|
public Artist[] Artists { get; set; }
|
||||||
|
public string[] AvailableMarkets { get; set; }
|
||||||
|
public Copyright[] Copyrights { get; set; }
|
||||||
|
public ExternalIds ExternalIds { get; set; }
|
||||||
|
public ExternalUrls ExternalUrls { get; set; }
|
||||||
|
public object[] Genres { get; set; }
|
||||||
|
public string Href { get; set; }
|
||||||
|
public string Id { get; set; }
|
||||||
|
public Image[] Images { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public long Popularity { get; set; }
|
||||||
|
public string ReleaseDate { get; set; }
|
||||||
|
public string ReleaseDatePrecision { get; set; }
|
||||||
|
public Tracks Tracks { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Tracks
|
||||||
|
{
|
||||||
|
public string Href { get; set; }
|
||||||
|
public Item[] Items { get; set; }
|
||||||
|
public long Limit { get; set; }
|
||||||
|
public object Next { get; set; }
|
||||||
|
public long Offset { get; set; }
|
||||||
|
public object Previous { get; set; }
|
||||||
|
public long Total { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Item
|
||||||
|
{
|
||||||
|
public Artist[] Artists { get; set; }
|
||||||
|
public string[] AvailableMarkets { get; set; }
|
||||||
|
public long DiscNumber { get; set; }
|
||||||
|
public long DurationMs { get; set; }
|
||||||
|
public bool Explicit { get; set; }
|
||||||
|
public ExternalUrls ExternalUrls { get; set; }
|
||||||
|
public string Href { get; set; }
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string PreviewUrl { get; set; }
|
||||||
|
public long TrackNumber { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Image
|
||||||
|
{
|
||||||
|
public long Height { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public long Width { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExternalIds
|
||||||
|
{
|
||||||
|
public string Upc { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Copyright
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Artist
|
||||||
|
{
|
||||||
|
public ExternalUrls ExternalUrls { get; set; }
|
||||||
|
public string Href { get; set; }
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExternalUrls
|
||||||
|
{
|
||||||
|
public string Spotify { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace MappersBenchmarks.Models;
|
||||||
|
|
||||||
|
public class SpotifyAlbumDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("album_type")] public string AlbumType { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("artists")] public ArtistDto[] Artists { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("available_markets")]
|
||||||
|
public string[] AvailableMarkets { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("copyrights")] public CopyrightDto[] Copyrights { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("external_ids")] public ExternalIdsDto ExternalIds { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("external_urls")] public ExternalUrlsDto ExternalUrls { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("genres")] public object[] Genres { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("href")] public string Href { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("id")] public string Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("images")] public ImageDto[] Images { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")] public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("popularity")] public long Popularity { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("release_date")] public string ReleaseDate { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("release_date_precision")]
|
||||||
|
public string ReleaseDatePrecision { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("tracks")] public TracksDto Tracks { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")] public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("uri")] public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TracksDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("href")] public string Href { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("items")] public ItemDto[] Items { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("limit")] public long Limit { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("next")] public object Next { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("offset")] public long Offset { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("previous")] public object Previous { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("total")] public long Total { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ItemDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("artists")] public ArtistDto[] Artists { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("available_markets")]
|
||||||
|
public string[] AvailableMarkets { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("disc_number")] public long DiscNumber { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("duration_ms")] public long DurationMs { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("explicit")] public bool Explicit { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("external_urls")] public ExternalUrlsDto ExternalUrls { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("href")] public string Href { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("id")] public string Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")] public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("preview_url")] public string PreviewUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("track_number")] public long TrackNumber { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")] public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("uri")] public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImageDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("height")] public long Height { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("url")] public string Url { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("width")] public long Width { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExternalIdsDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("upc")] public string Upc { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CopyrightDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("text")] public string Text { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")] public string Type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArtistDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("external_urls")] public ExternalUrlsDto ExternalUrls { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("href")] public string Href { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("id")] public string Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")] public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")] public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("uri")] public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExternalUrlsDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("spotify")] public string Spotify { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using MappersBenchmarks;
|
||||||
|
|
||||||
|
BenchmarkRunner.Run<Benchmarks>();
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
using MappersBenchmarks.Models;
|
||||||
|
|
||||||
|
namespace MappersBenchmarks;
|
||||||
|
|
||||||
|
public static class TestData
|
||||||
|
{
|
||||||
|
public static SpotifyAlbumDto ExampleAlbum = new SpotifyAlbumDto
|
||||||
|
{
|
||||||
|
AlbumType = "album",
|
||||||
|
Artists = new[]
|
||||||
|
{
|
||||||
|
new ArtistDto
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrlsDto
|
||||||
|
{
|
||||||
|
Spotify = "https://open.spotify.com/artist/o8fn439te8tgeu"
|
||||||
|
},
|
||||||
|
Href = "https://api.spotify.com/v1/artists/j9t8w5t549jw4i",
|
||||||
|
Id = "r8eht9778tjh34w8t4",
|
||||||
|
Name = "Nick Chapsas",
|
||||||
|
Type = "artist",
|
||||||
|
Uri = "spotify:artist:r8eht9778tjh34w8t4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AvailableMarkets = new[]
|
||||||
|
{
|
||||||
|
"AD",
|
||||||
|
"AR",
|
||||||
|
"AT",
|
||||||
|
"AU",
|
||||||
|
"BE",
|
||||||
|
"BG",
|
||||||
|
"BO",
|
||||||
|
"BR",
|
||||||
|
"CA",
|
||||||
|
"CH",
|
||||||
|
"CL",
|
||||||
|
"CO",
|
||||||
|
"CR",
|
||||||
|
"CY",
|
||||||
|
"CZ",
|
||||||
|
"DE",
|
||||||
|
"DK",
|
||||||
|
"DO",
|
||||||
|
"EC",
|
||||||
|
"EE",
|
||||||
|
"ES",
|
||||||
|
"FI",
|
||||||
|
"FR",
|
||||||
|
"GB",
|
||||||
|
"GR",
|
||||||
|
"GT",
|
||||||
|
"HK",
|
||||||
|
"HN",
|
||||||
|
"HU",
|
||||||
|
"IE",
|
||||||
|
"IS",
|
||||||
|
"IT",
|
||||||
|
"LI",
|
||||||
|
"LT",
|
||||||
|
"LU",
|
||||||
|
"LV",
|
||||||
|
"MC",
|
||||||
|
"MT",
|
||||||
|
"MX",
|
||||||
|
"MY",
|
||||||
|
"NI",
|
||||||
|
"NL",
|
||||||
|
"NO",
|
||||||
|
"NZ",
|
||||||
|
"PA",
|
||||||
|
"PE",
|
||||||
|
"PH",
|
||||||
|
"PT",
|
||||||
|
"PY",
|
||||||
|
"RO",
|
||||||
|
"SE",
|
||||||
|
"SG",
|
||||||
|
"SI",
|
||||||
|
"SK",
|
||||||
|
"SV",
|
||||||
|
"TW",
|
||||||
|
"UY"
|
||||||
|
},
|
||||||
|
Copyrights = new[]
|
||||||
|
{
|
||||||
|
new CopyrightDto
|
||||||
|
{
|
||||||
|
Text = "(P) 2000 Sony Music Entertainment Inc.",
|
||||||
|
Type = "P"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExternalIds = new ExternalIdsDto
|
||||||
|
{
|
||||||
|
Upc = "4873965873469874"
|
||||||
|
},
|
||||||
|
ExternalUrls = new ExternalUrlsDto
|
||||||
|
{
|
||||||
|
Spotify = "https://open.spotify.com/album/98etu0j9r54yjr9y0oj"
|
||||||
|
},
|
||||||
|
Genres = Array.Empty<object>(),
|
||||||
|
Href = "https://api.spotify.com/v1/albums/98etu0j9r54yjr9y0oj",
|
||||||
|
Id = "984rjyj940y549",
|
||||||
|
Images = new[]
|
||||||
|
{
|
||||||
|
new ImageDto
|
||||||
|
{
|
||||||
|
Height = 69,
|
||||||
|
Width = 420,
|
||||||
|
Url = "https://i.scdn.co/image/gunejg4e95g9u54g0w94"
|
||||||
|
},
|
||||||
|
new ImageDto
|
||||||
|
{
|
||||||
|
Height = 69,
|
||||||
|
Width = 420,
|
||||||
|
Url = "https://i.scdn.co/image/5e675t6u856t"
|
||||||
|
},
|
||||||
|
new ImageDto
|
||||||
|
{
|
||||||
|
Height = 69,
|
||||||
|
Width = 420,
|
||||||
|
Url = "https://i.scdn.co/image/56rur65ur6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Name = "Keep coding",
|
||||||
|
Popularity = 69,
|
||||||
|
ReleaseDate = "1969",
|
||||||
|
ReleaseDatePrecision = "year",
|
||||||
|
Tracks = new TracksDto
|
||||||
|
{
|
||||||
|
Href = "https://api.spotify.com/v1/albums/e67u567ue567/tracks?offset=0&limit=50",
|
||||||
|
Items = new[]
|
||||||
|
{
|
||||||
|
new ItemDto
|
||||||
|
{
|
||||||
|
Artists = new[]
|
||||||
|
{
|
||||||
|
new ArtistDto
|
||||||
|
{
|
||||||
|
ExternalUrls = new ExternalUrlsDto
|
||||||
|
{
|
||||||
|
Spotify = "https://open.spotify.com/artist/43y654ry64rs56y4w"
|
||||||
|
},
|
||||||
|
Href = "https://api.spotify.com/v1/artists/h8w79tr8e9th",
|
||||||
|
Id = "h3r34ai8o7ht8goiu8a",
|
||||||
|
Name = "Nick Chapsas",
|
||||||
|
Type = "artist",
|
||||||
|
Uri = "spotify:artist:w6456ywe5y6r6yr"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DiscNumber = 1,
|
||||||
|
DurationMs = 42069,
|
||||||
|
Explicit = false,
|
||||||
|
Name = "Cmon this is too long",
|
||||||
|
TrackNumber = 1,
|
||||||
|
Type = "track",
|
||||||
|
ExternalUrls = new ExternalUrlsDto
|
||||||
|
{
|
||||||
|
Spotify = "spotify:artist:w6456ywe5y6r6yr"
|
||||||
|
},
|
||||||
|
PreviewUrl = "https://p.scdn.co/mp3-preview/3y487th43f98t8347ht89734h98tfh3498frth",
|
||||||
|
Uri = "spotify:track:t8e4t98h4w5ht4i",
|
||||||
|
AvailableMarkets = new[]
|
||||||
|
{
|
||||||
|
"AD",
|
||||||
|
"AR",
|
||||||
|
"AT",
|
||||||
|
"AU",
|
||||||
|
"BE",
|
||||||
|
"BG",
|
||||||
|
"BO",
|
||||||
|
"BR",
|
||||||
|
"CA",
|
||||||
|
"CH",
|
||||||
|
"CL",
|
||||||
|
"CO",
|
||||||
|
"CR",
|
||||||
|
"CY",
|
||||||
|
"CZ",
|
||||||
|
"DE",
|
||||||
|
"DK",
|
||||||
|
"DO",
|
||||||
|
"EC",
|
||||||
|
"EE",
|
||||||
|
"ES",
|
||||||
|
"FI",
|
||||||
|
"FR",
|
||||||
|
"GB",
|
||||||
|
"GR",
|
||||||
|
"GT",
|
||||||
|
"HK",
|
||||||
|
"HN",
|
||||||
|
"HU",
|
||||||
|
"IE",
|
||||||
|
"IS",
|
||||||
|
"IT",
|
||||||
|
"LI",
|
||||||
|
"LT",
|
||||||
|
"LU",
|
||||||
|
"LV",
|
||||||
|
"MC",
|
||||||
|
"MT",
|
||||||
|
"MX",
|
||||||
|
"MY",
|
||||||
|
"NI",
|
||||||
|
"NL",
|
||||||
|
"NO",
|
||||||
|
"NZ",
|
||||||
|
"PA",
|
||||||
|
"PE",
|
||||||
|
"PH",
|
||||||
|
"PT",
|
||||||
|
"PY",
|
||||||
|
"RO",
|
||||||
|
"SE",
|
||||||
|
"SG",
|
||||||
|
"SI",
|
||||||
|
"SK",
|
||||||
|
"SV",
|
||||||
|
"TW",
|
||||||
|
"UY"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Limit = 50,
|
||||||
|
Offset = 0,
|
||||||
|
Total = 13
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user