Skip to content

Commit 45bb654

Browse files
committed
Performance improvements
1 parent 940f6b1 commit 45bb654

File tree

17 files changed

+84
-50
lines changed

17 files changed

+84
-50
lines changed

AgileMapper.PerformanceTesting/PerformanceTestRunner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private static ICollection<IObjectMapperTest> GetMapperTestsFor(Type exampleMapp
4242
.GetTypes()
4343
.Filter(t => (t.Namespace == exampleMapperTestType.Namespace) && typeof(IObjectMapperTest).IsAssignableFrom(t))
4444
.Project(CreateTest)
45-
.ToList();
45+
.ToArray();
4646
}
4747

4848
private static IObjectMapperTest CreateTest(Type testType)

AgileMapper/Configuration/ConfiguredLambdaInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private ConfiguredLambdaInfo(
4040

4141
public static ConfiguredLambdaInfo For(LambdaExpression lambda)
4242
{
43-
var funcArguments = lambda.Parameters.Project(p => p.Type).ToArray();
43+
var funcArguments = lambda.Parameters.ProjectToArray(p => p.Type);
4444
var contextTypes = GetContextTypes(funcArguments);
4545
var parameterSwapper = ParametersSwapper.For(contextTypes, funcArguments);
4646

@@ -120,7 +120,7 @@ private static ConfiguredLambdaInfo For<T>(
120120
return null;
121121
}
122122

123-
var parameters = funcArguments.Project(Parameters.Create).ToArray();
123+
var parameters = funcArguments.ProjectToArray(Parameters.Create);
124124
var valueFactory = func.ToConstantExpression();
125125
var valueFactoryInvocation = Expression.Invoke(valueFactory, parameters.Cast<Expression>());
126126
var valueFactoryLambda = Expression.Lambda(funcType, valueFactoryInvocation, parameters);

AgileMapper/Configuration/DerivedTypePairSet.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,11 @@ private void LookForDerivedTypePairs(ITypePair mapperData, MapperContext mapperC
135135
return;
136136
}
137137

138-
var candidatePairsData = derivedSourceTypes
139-
.Project(t => new
140-
{
141-
DerivedSourceType = t,
142-
DerivedTargetTypeName = derivedTargetTypeNameFactory.Invoke(t)
143-
})
144-
.ToArray();
138+
var candidatePairsData = derivedSourceTypes.ProjectToArray(t => new
139+
{
140+
DerivedSourceType = t,
141+
DerivedTargetTypeName = derivedTargetTypeNameFactory.Invoke(t)
142+
});
145143

146144
foreach (var candidatePairData in candidatePairsData)
147145
{

AgileMapper/Configuration/Inline/InlineMapperContextSet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private MapperContext GetContextFor<TSource, TTarget, TConfigurator>(
5959
{
6060
var key = new InlineMapperKey<TSource, TTarget, TConfigurator>(
6161
#if NET35
62-
configurations.Project(c => c.ToDlrExpression()).ToArray(),
62+
configurations.ProjectToArray(c => c.ToDlrExpression()),
6363
#else
6464
configurations,
6565
#endif

AgileMapper/Configuration/ParametersSwapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private static Expression ReplaceParameters(
165165
{
166166
var contextInfo = GetAppropriateMappingContext(swapArgs);
167167

168-
return swapArgs.Lambda.ReplaceParametersWith(parameterFactories.Project(f => f.Invoke(contextInfo)).ToArray());
168+
return swapArgs.Lambda.ReplaceParametersWith(parameterFactories.ProjectToArray(f => f.Invoke(contextInfo)));
169169
}
170170

171171
private static MappingContextInfo GetAppropriateMappingContext(SwapArgs swapArgs)

AgileMapper/DerivedTypesCache.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ internal class DerivedTypesCache
1515

1616
private readonly List<Assembly> _assemblies;
1717
private readonly ICache<Assembly, IEnumerable<Type>> _typesByAssembly;
18-
private readonly ICache<Type, ICollection<Type>> _derivedTypesByType;
18+
private readonly ICache<Type, IList<Type>> _derivedTypesByType;
1919

2020
public DerivedTypesCache(CacheSet cacheSet)
2121
{
2222
_assemblies = new List<Assembly>();
2323
_typesByAssembly = cacheSet.CreateScoped<Assembly, IEnumerable<Type>>(default(HashCodeComparer<Assembly>));
24-
_derivedTypesByType = cacheSet.CreateScoped<Type, ICollection<Type>>(default(HashCodeComparer<Type>));
24+
_derivedTypesByType = cacheSet.CreateScoped<Type, IList<Type>>(default(HashCodeComparer<Type>));
2525
}
2626

2727
public void AddAssemblies(Assembly[] assemblies)
@@ -32,7 +32,7 @@ public void AddAssemblies(Assembly[] assemblies)
3232
}
3333
}
3434

35-
public ICollection<Type> GetTypesDerivedFrom(Type type)
35+
public IList<Type> GetTypesDerivedFrom(Type type)
3636
{
3737
if (type.IsSealed() || type.IsFromBcl())
3838
{
@@ -42,7 +42,7 @@ public ICollection<Type> GetTypesDerivedFrom(Type type)
4242
return _derivedTypesByType.GetOrAdd(type, GetDerivedTypesForType);
4343
}
4444

45-
private ICollection<Type> GetDerivedTypesForType(Type type)
45+
private IList<Type> GetDerivedTypesForType(Type type)
4646
{
4747
var typeAssemblies = new[] { type.GetAssembly() };
4848

AgileMapper/Extensions/Internal/EnumerableExtensions.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,30 @@ public static bool All<T>(this IList<T> items, Func<T, bool> predicate)
123123
[DebuggerStepThrough]
124124
public static bool HasOne<T>(this ICollection<T> items) => items.Count == 1;
125125

126+
public static TResult[] ProjectToArray<TItem, TResult>(this IList<TItem> items, Func<TItem, TResult> projector)
127+
{
128+
var itemCount = items.Count;
129+
130+
if (itemCount == 0)
131+
{
132+
return Enumerable<TResult>.EmptyArray;
133+
}
134+
135+
var result = new TResult[items.Count];
136+
137+
for (var i = 0; ;)
138+
{
139+
result[i] = projector.Invoke(items[i]);
140+
141+
if (++i == itemCount)
142+
{
143+
break;
144+
}
145+
}
146+
147+
return result;
148+
}
149+
126150
public static Expression ReverseChain<T>(this IList<T> items)
127151
where T : IConditionallyChainable
128152
{

AgileMapper/Extensions/Internal/ExpressionExtensions.Replace.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ private Expression ReplaceIn(BlockExpression block)
236236
{
237237
return ReplaceIn(
238238
block,
239-
b => b.Update(b.Variables.Project(ReplaceIn), b.Expressions.Project(Replace)));
239+
b => b.Update(b.Variables.ProjectToArray(ReplaceIn), b.Expressions.ProjectToArray(Replace)));
240240
}
241241

242242
private Expression ReplaceIn(MethodCallExpression call)
@@ -247,29 +247,29 @@ private Expression ReplaceIn(MethodCallExpression call)
247247
private Expression ReplaceIn(GotoExpression @goto) => ReplaceIn(@goto, gt => gt.Update(gt.Target, Replace(gt.Value)));
248248

249249
private Expression ReplaceIn(IndexExpression indexAccess)
250-
=> ReplaceIn(indexAccess, idx => idx.Update(Replace(idx.Object), idx.Arguments.Project(Replace)));
250+
=> ReplaceIn(indexAccess, idx => idx.Update(Replace(idx.Object), idx.Arguments.ProjectToArray(Replace)));
251251

252252
private Expression ReplaceIn(InvocationExpression invocation)
253253
=> ReplaceIn(invocation, inv => ReplaceInCall(inv.Expression, inv.Arguments, inv.Update));
254254

255255
private Expression ReplaceInCall(
256256
Expression subject,
257-
IEnumerable<Expression> arguments,
257+
IList<Expression> arguments,
258258
Func<Expression, IEnumerable<Expression>, Expression> replacer)
259259
{
260-
return replacer.Invoke(Replace(subject), arguments.Project(Replace).ToArray());
260+
return replacer.Invoke(Replace(subject), arguments.ProjectToArray(Replace));
261261
}
262262

263263
private Expression ReplaceIn(LabelExpression label)
264264
=> ReplaceIn(label, l => l.Update(l.Target, Replace(l.DefaultValue)));
265265

266266
private Expression ReplaceIn(LambdaExpression lambda)
267-
=> ReplaceIn(lambda, l => Expression.Lambda(l.Type, Replace(l.Body), l.Parameters.Project(ReplaceIn)));
267+
=> ReplaceIn(lambda, l => Expression.Lambda(l.Type, Replace(l.Body), l.Parameters.ProjectToArray(ReplaceIn)));
268268

269269
private Expression ReplaceIn(MemberExpression memberAccess) => ReplaceIn(memberAccess, ma => ma.Update(Replace(ma.Expression)));
270270

271271
private Expression ReplaceIn(MemberInitExpression memberInit)
272-
=> ReplaceIn(memberInit, mi => mi.Update(ReplaceInNew(mi.NewExpression), mi.Bindings.Project(ReplaceIn)));
272+
=> ReplaceIn(memberInit, mi => mi.Update(ReplaceInNew(mi.NewExpression), mi.Bindings.ProjectToArray(ReplaceIn)));
273273

274274
private Expression ReplaceIn(ListInitExpression listInit)
275275
=> ReplaceIn(listInit, li => li.Update(ReplaceInNew(li.NewExpression), ReplaceIn(li.Initializers)));
@@ -290,25 +290,25 @@ private MemberBinding ReplaceIn(MemberBinding binding)
290290

291291
case MemberBindingType.MemberBinding:
292292
var memberBinding = (MemberMemberBinding)binding;
293-
return memberBinding.Update(memberBinding.Bindings.Project(ReplaceIn));
293+
return memberBinding.Update(memberBinding.Bindings.ProjectToArray(ReplaceIn));
294294
}
295295

296296
throw new ArgumentOutOfRangeException();
297297
}
298298

299-
private IEnumerable<ElementInit> ReplaceIn(IEnumerable<ElementInit> initializers)
300-
=> initializers.Project(init => init.Update(init.Arguments.Project(Replace)));
299+
private IEnumerable<ElementInit> ReplaceIn(IList<ElementInit> initializers)
300+
=> initializers.ProjectToArray(init => init.Update(init.Arguments.ProjectToArray(Replace)));
301301

302302
private Expression ReplaceIn(NewExpression newing) => ReplaceIn(newing, ReplaceInNew);
303303

304304
private NewExpression ReplaceInNew(NewExpression newing)
305305
{
306306
return newing.Arguments.None()
307307
? newing
308-
: newing.Update(newing.Arguments.Project(Replace));
308+
: newing.Update(newing.Arguments.ProjectToArray(Replace));
309309
}
310310

311-
private Expression ReplaceIn(NewArrayExpression newArray) => ReplaceIn(newArray, na => na.Update(na.Expressions.Project(Replace)));
311+
private Expression ReplaceIn(NewArrayExpression newArray) => ReplaceIn(newArray, na => na.Update(na.Expressions.ProjectToArray(Replace)));
312312

313313
private ParameterExpression ReplaceIn(ParameterExpression parameter) => (ParameterExpression)ReplaceIn(parameter, p => p);
314314

@@ -320,7 +320,7 @@ private Expression ReplaceIn(TryExpression @try)
320320
{
321321
return ReplaceIn(
322322
@try,
323-
t => t.Update(Replace(t.Body), t.Handlers.Project(ReplaceIn), Replace(t.Finally), Replace(t.Fault)));
323+
t => t.Update(Replace(t.Body), t.Handlers.ProjectToArray(ReplaceIn), Replace(t.Finally), Replace(t.Fault)));
324324
}
325325

326326
private CatchBlock ReplaceIn(CatchBlock @catch)

AgileMapper/Extensions/Internal/TypeExtensions.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,29 @@ private static double GetValueFor(
189189
{
190190
type = type.GetNonNullableType();
191191

192-
return type.IsEnum() ? enumValueFactory.Invoke(GetEnumValues(type)) : cache[type];
192+
return type.IsEnum() ? enumValueFactory.Invoke(GetEnumValuesArray(type, Convert.ToInt64)) : cache[type];
193193
}
194194

195-
private static IEnumerable<long> GetEnumValues(Type enumType)
196-
=> Enum.GetValues(enumType).Cast<object>().Project(Convert.ToInt64);
195+
public static TResult[] GetEnumValuesArray<TResult>(this Type enumType, Func<object, TResult> resultFactory)
196+
{
197+
var values = Enum.GetValues(enumType);
198+
var valueCount = values.Length;
199+
200+
if (valueCount == 0)
201+
{
202+
return Enumerable<TResult>.EmptyArray;
203+
}
204+
205+
var resultValues = new TResult[valueCount];
206+
var i = 0;
207+
208+
foreach (var value in values)
209+
{
210+
resultValues[i++] = resultFactory.Invoke(value);
211+
}
212+
213+
return resultValues;
214+
}
197215

198216
public static bool StartsWith(this string value, char character) => value[0] == character;
199217

AgileMapper/Members/Dictionaries/DictionaryTargetMember.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ private static Expression GetCheckedTryCatch(
336336

337337
var updatedCatchHandlers = tryCatchValue
338338
.Handlers
339-
.Project(handler => handler.Update(
339+
.ProjectToArray(handler => handler.Update(
340340
handler.Variable,
341341
handler.Filter.Replace(replacements),
342342
handler.Body.Replace(replacements)));

0 commit comments

Comments
 (0)