mirror of
https://github.com/ppy/osu.git
synced 2025-02-16 02:23:10 +08:00
Create separate automapper configurations to reduce cyclic detach overhead
This optimises the `BeatmapSetInfo` detach operation by avoiding detaching `BeatmapSetInfo.Beatmaps[].BeatmapSetInfo` a second time over.
This commit is contained in:
parent
66ed4270c0
commit
f2b151023e
@ -74,21 +74,10 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private static readonly IMapper mapper = new MapperConfiguration(c =>
|
private static readonly IMapper mapper = new MapperConfiguration(c =>
|
||||||
{
|
{
|
||||||
c.ShouldMapField = fi => false;
|
applyCommonConfiguration(c);
|
||||||
|
|
||||||
// This is specifically to avoid mapping explicit interface implementations.
|
// This can be further optimised to reduce cyclic retrievals, similar to the optimised set mapper below.
|
||||||
// If we want to limit this further, we can avoid mapping properties with no setter that are not IList<>.
|
// Only hasn't been done yet as we detach at the point of BeatmapInfo less often.
|
||||||
// Takes a bit of effort to determine whether this is the case though, see https://stackoverflow.com/questions/951536/how-do-i-tell-whether-a-type-implements-ilist
|
|
||||||
c.ShouldMapProperty = pi => pi.GetMethod?.IsPublic == true;
|
|
||||||
|
|
||||||
c.CreateMap<RealmKeyBinding, RealmKeyBinding>();
|
|
||||||
c.CreateMap<BeatmapMetadata, BeatmapMetadata>();
|
|
||||||
c.CreateMap<BeatmapDifficulty, BeatmapDifficulty>();
|
|
||||||
c.CreateMap<RulesetInfo, RulesetInfo>();
|
|
||||||
c.CreateMap<ScoreInfo, ScoreInfo>();
|
|
||||||
c.CreateMap<RealmUser, RealmUser>();
|
|
||||||
c.CreateMap<RealmFile, RealmFile>();
|
|
||||||
c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>();
|
|
||||||
c.CreateMap<BeatmapInfo, BeatmapInfo>()
|
c.CreateMap<BeatmapInfo, BeatmapInfo>()
|
||||||
.MaxDepth(2)
|
.MaxDepth(2)
|
||||||
.AfterMap((s, d) =>
|
.AfterMap((s, d) =>
|
||||||
@ -102,13 +91,28 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
c.CreateMap<BeatmapSetInfo, BeatmapSetInfo>()
|
}).CreateMapper();
|
||||||
.MaxDepth(2)
|
|
||||||
.AfterMap((s, d) =>
|
/// <summary>
|
||||||
{
|
/// A slightly optimised mapper that avoids double-fetches in cyclic reference.
|
||||||
foreach (var beatmap in d.Beatmaps)
|
/// </summary>
|
||||||
beatmap.BeatmapSet = d;
|
private static readonly IMapper beatmap_set_mapper = new MapperConfiguration(c =>
|
||||||
});
|
{
|
||||||
|
applyCommonConfiguration(c);
|
||||||
|
|
||||||
|
c.CreateMap<BeatmapInfo, BeatmapInfo>()
|
||||||
|
.MaxDepth(1)
|
||||||
|
.ForMember(b => b.BeatmapSet, cc => cc.Ignore());
|
||||||
|
}).CreateMapper();
|
||||||
|
|
||||||
|
private static void applyCommonConfiguration(IMapperConfigurationExpression c)
|
||||||
|
{
|
||||||
|
c.ShouldMapField = fi => false;
|
||||||
|
|
||||||
|
// This is specifically to avoid mapping explicit interface implementations.
|
||||||
|
// If we want to limit this further, we can avoid mapping properties with no setter that are not IList<>.
|
||||||
|
// Takes a bit of effort to determine whether this is the case though, see https://stackoverflow.com/questions/951536/how-do-i-tell-whether-a-type-implements-ilist
|
||||||
|
c.ShouldMapProperty = pi => pi.GetMethod?.IsPublic == true;
|
||||||
|
|
||||||
c.Internal().ForAllMaps((typeMap, expression) =>
|
c.Internal().ForAllMaps((typeMap, expression) =>
|
||||||
{
|
{
|
||||||
@ -118,7 +122,23 @@ namespace osu.Game.Database
|
|||||||
m.Ignore();
|
m.Ignore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).CreateMapper();
|
|
||||||
|
c.CreateMap<RealmKeyBinding, RealmKeyBinding>();
|
||||||
|
c.CreateMap<BeatmapMetadata, BeatmapMetadata>();
|
||||||
|
c.CreateMap<BeatmapDifficulty, BeatmapDifficulty>();
|
||||||
|
c.CreateMap<RulesetInfo, RulesetInfo>();
|
||||||
|
c.CreateMap<ScoreInfo, ScoreInfo>();
|
||||||
|
c.CreateMap<RealmUser, RealmUser>();
|
||||||
|
c.CreateMap<RealmFile, RealmFile>();
|
||||||
|
c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>();
|
||||||
|
c.CreateMap<BeatmapSetInfo, BeatmapSetInfo>()
|
||||||
|
.MaxDepth(2)
|
||||||
|
.AfterMap((s, d) =>
|
||||||
|
{
|
||||||
|
foreach (var beatmap in d.Beatmaps)
|
||||||
|
beatmap.BeatmapSet = d;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a detached copy of the each item in the collection.
|
/// Create a detached copy of the each item in the collection.
|
||||||
@ -153,6 +173,9 @@ namespace osu.Game.Database
|
|||||||
if (!item.IsManaged)
|
if (!item.IsManaged)
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
|
if (item is BeatmapSetInfo)
|
||||||
|
return beatmap_set_mapper.Map<T>(item);
|
||||||
|
|
||||||
return mapper.Map<T>(item);
|
return mapper.Map<T>(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user