Skip to content

Commit 815edf7

Browse files
authored
Optimize ItemProjectorExpression (#391)
1 parent 8c53452 commit 815edf7

File tree

10 files changed

+83
-49
lines changed

10 files changed

+83
-49
lines changed

Orm/Xtensive.Orm/Linq/ExpressionWriter.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -476,19 +476,20 @@ protected override InvocationExpression VisitInvocation(InvocationExpression i)
476476
/// <inheritdoc/>
477477
protected override LambdaExpression VisitLambda<T>(Expression<T> l)
478478
{
479-
if (l.Parameters.Count > 1) {
479+
var lambdaParameters = l.Parameters;
480+
if (lambdaParameters.Count > 1) {
480481
Write("(");
481-
for (int i = 0, n = l.Parameters.Count; i < n; i++) {
482-
Write(l.Parameters[i].Name);
482+
for (int i = 0, n = lambdaParameters.Count; i < n; i++) {
483+
Write(lambdaParameters[i].Name);
483484
if (i < n - 1) {
484485
Write(", ");
485486
}
486487
}
487488

488489
Write(")");
489490
}
490-
else if (l.Parameters.Count == 1) {
491-
Write(l.Parameters[0].Name);
491+
else if (lambdaParameters.Count == 1) {
492+
Write(lambdaParameters[0].Name);
492493
}
493494
else {
494495
Write("()");
@@ -657,4 +658,4 @@ public ExpressionWriter(TextWriter writer, int indentSize)
657658
this.indentSize = indentSize;
658659
}
659660
}
660-
}
661+
}

Orm/Xtensive.Orm/Linq/Internals/ExpressionHashCodeCalculator.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ protected override int VisitMemberAccess(MemberExpression m) =>
5959

6060
protected override int VisitLambda(LambdaExpression l)
6161
{
62-
parameters.AddRange(l.Parameters);
63-
return HashCode.Combine(HashExpressionSequence(l.Parameters.Cast<Expression>()), Visit(l.Body));
62+
var lambdaParameters = l.Parameters;
63+
parameters.AddRange(lambdaParameters);
64+
return HashCode.Combine(HashExpressionSequence(lambdaParameters), Visit(l.Body));
6465
}
6566

6667
protected override int VisitNew(NewExpression n) =>

Orm/Xtensive.Orm/Orm/Building/Builders/AttributeProcessor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ private LambdaExpression GetExpressionFromProvider(Type providerType, string pro
473473
}
474474

475475
var expression = (LambdaExpression) method.Invoke(null, Array.Empty<object>());
476-
if (expression.Parameters.Count != 1 || !expression.Parameters[0].Type.IsAssignableFrom(parameterType)) {
476+
var expressionParameters = expression.Parameters;
477+
if (expressionParameters.Count != 1 || !expressionParameters[0].Type.IsAssignableFrom(parameterType)) {
477478
throw new DomainBuilderException(string.Format(
478479
Strings.ExLambdaExpressionReturnedByXShouldTakeOneParameterOfTypeYOrAnyBaseTypeOfIt, memberName,
479480
parameterType.FullName));

Orm/Xtensive.Orm/Orm/Linq/Expressions/ExtendedExpressionType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
namespace Xtensive.Orm.Linq.Expressions
1010
{
1111
[Serializable]
12-
internal enum ExtendedExpressionType
12+
internal enum ExtendedExpressionType : short
1313
{
1414
Projection = 1000,
1515
Key,
@@ -28,4 +28,4 @@ internal enum ExtendedExpressionType
2828
Constructor,
2929
FullText
3030
}
31-
}
31+
}

Orm/Xtensive.Orm/Orm/Linq/Expressions/ItemProjectorExpression.cs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
// Created by: Alexis Kochetov
55
// Created: 2009.05.06
66

7-
using System;
8-
using System.Collections.Generic;
9-
using System.Linq;
107
using System.Linq.Expressions;
118
using Xtensive.Core;
129
using Xtensive.Orm.Linq.Expressions.Visitors;
@@ -53,19 +50,38 @@ public IReadOnlyList<ColNum> GetColumns(ColumnExtractionModes columnExtractionMo
5350

5451
public ItemProjectorExpression Remap(CompilableProvider dataSource, ColNum offset)
5552
{
56-
if (offset == 0) {
57-
return new ItemProjectorExpression(Item, dataSource, Context, AggregateType);
53+
var item = Item;
54+
if (offset != 0) {
55+
Dictionary<Expression, Expression> dict = null;
56+
item = GenericExpressionVisitor<IMappedExpression>.Process(Item, mapped => {
57+
if (dict == null) {
58+
dict = new();
59+
}
60+
else {
61+
dict.Clear();
62+
}
63+
64+
return mapped.Remap(offset, dict);
65+
});
5866
}
5967

60-
var item = GenericExpressionVisitor<IMappedExpression>
61-
.Process(Item, mapped => mapped.Remap(offset, new Dictionary<Expression, Expression>()));
6268
return new ItemProjectorExpression(item, dataSource, Context, AggregateType);
6369
}
6470

6571
public ItemProjectorExpression Remap(CompilableProvider dataSource, ColumnMap columnMap)
6672
{
73+
Dictionary<Expression, Expression> dict = null;
6774
var item = GenericExpressionVisitor<IMappedExpression>
68-
.Process(Item, mapped => mapped.Remap(columnMap, new Dictionary<Expression, Expression>()));
75+
.Process(Item, mapped => {
76+
if (dict == null) {
77+
dict = new();
78+
}
79+
else {
80+
dict.Clear();
81+
}
82+
83+
return mapped.Remap(columnMap, dict);
84+
});
6985
return new ItemProjectorExpression(item, dataSource, Context, AggregateType);
7086
}
7187

@@ -83,8 +99,17 @@ public ItemProjectorExpression BindOuterParameter(ParameterExpression parameter)
8399

84100
public ItemProjectorExpression RemoveOuterParameter()
85101
{
102+
Dictionary<Expression, Expression> dict = null;
86103
var item = GenericExpressionVisitor<IMappedExpression>
87-
.Process(Item, mapped => mapped.RemoveOuterParameter(new Dictionary<Expression, Expression>()));
104+
.Process(Item, mapped => {
105+
if (dict == null) {
106+
dict = new();
107+
}
108+
else {
109+
dict.Clear();
110+
}
111+
return mapped.RemoveOuterParameter(dict);
112+
});
88113
return new ItemProjectorExpression(item, DataSource, Context, AggregateType);
89114
}
90115

Orm/Xtensive.Orm/Orm/Linq/Rewriters/AggregateOptimizer.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ public static List<LambdaExpression> Execute(LambdaExpression expression)
5757
// i => i.Acitve ? i.Value : 0
5858

5959
var finder = new AggregateProjectionFinder();
60-
finder.aggregatedSequence = expression.Parameters.Count==2
61-
? expression.Parameters[1] // Result selector parameter in GroupBy
62-
: expression.Parameters[0]; // Selector parameter in Select after GroupBy
60+
var expressionParameters = expression.Parameters;
61+
finder.aggregatedSequence = expressionParameters.Count==2
62+
? expressionParameters[1] // Result selector parameter in GroupBy
63+
: expressionParameters[0]; // Selector parameter in Select after GroupBy
6364
finder.Visit(expression);
6465
return finder.result;
6566
}

Orm/Xtensive.Orm/Orm/Linq/Translator.Queryable.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,11 @@ private ProjectionExpression CombineProjections(ProjectionExpression outer, Proj
12571257
outer = new ProjectionExpression(outer.Type, outer.ItemProjector.Remap(recordQuery, 0), tupleParameterBindings);
12581258
inner = new ProjectionExpression(inner.Type, inner.ItemProjector.Remap(recordQuery, outerLength), tupleParameterBindings);
12591259

1260-
context.Bindings.PermanentAdd(resultSelector.Parameters[0], outer);
1261-
context.Bindings.PermanentAdd(resultSelector.Parameters[1], inner);
1262-
using (context.Bindings.LinkParameters(resultSelector.Parameters)) {
1260+
var contextBindings = context.Bindings;
1261+
var resultSelectorParameters = resultSelector.Parameters;
1262+
contextBindings.PermanentAdd(resultSelectorParameters[0], outer);
1263+
contextBindings.PermanentAdd(resultSelectorParameters[1], inner);
1264+
using (contextBindings.LinkParameters(resultSelectorParameters)) {
12631265
return BuildProjection(resultSelector);
12641266
}
12651267
}
@@ -1416,12 +1418,13 @@ private ProjectionExpression VisitSelectMany(Expression source, LambdaExpression
14161418
private ProjectionExpression VisitSelect(Expression expression, LambdaExpression le)
14171419
{
14181420
var sequence = VisitSequence(expression);
1419-
if (le.Parameters.Count == 2) {
1421+
var leParameters = le.Parameters;
1422+
if (leParameters.Count == 2) {
14201423
var indexProjection = GetIndexBinding(le, ref sequence);
1421-
context.Bindings.PermanentAdd(le.Parameters[1], indexProjection);
1424+
context.Bindings.PermanentAdd(leParameters[1], indexProjection);
14221425
}
14231426

1424-
context.Bindings.PermanentAdd(le.Parameters[0], sequence);
1427+
context.Bindings.PermanentAdd(leParameters[0], sequence);
14251428
var calculateExpressions = State.RequestCalculateExpressions || State.RequestCalculateExpressionsOnce;
14261429
using (CreateScope(new TranslatorState(State) {
14271430
CalculateExpressions = calculateExpressions,
@@ -1444,12 +1447,13 @@ private ProjectionExpression BuildProjection(LambdaExpression le)
14441447

14451448
private ProjectionExpression VisitWhere(Expression expression, LambdaExpression le)
14461449
{
1447-
var parameter = le.Parameters[0];
1450+
var leParameters = le.Parameters;
1451+
var parameter = leParameters[0];
14481452
var visitedSource = VisitSequence(expression);
14491453
var indexBinding = BindingCollection<ParameterExpression, ProjectionExpression>.BindingScope.Empty;
1450-
if (le.Parameters.Count == 2) {
1454+
if (leParameters.Count == 2) {
14511455
var indexProjection = GetIndexBinding(le, ref visitedSource);
1452-
indexBinding = context.Bindings.Add(le.Parameters[1], indexProjection);
1456+
indexBinding = context.Bindings.Add(leParameters[1], indexProjection);
14531457
}
14541458

14551459
using (indexBinding)

Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -450,16 +450,14 @@ protected override SqlExpression VisitLambda(LambdaExpression l)
450450
{
451451
if (activeParameters.Count>0)
452452
throw new InvalidOperationException();
453-
activeParameters.AddRange(l.Parameters);
454-
for (int i = 0, count = l.Parameters.Count; i < count; i++) {
455-
var p = l.Parameters[i];
453+
var lParameters = l.Parameters;
454+
activeParameters.AddRange(lParameters);
455+
for (int i = 0, count = lParameters.Count; i < count; i++) {
456+
var p = lParameters[i];
456457
sourceMapping[p] = sourceColumns[i];
457458
}
458459
var body = Visit(l.Body);
459-
var sqlContainer = body as SqlContainer;
460-
if (sqlContainer is not null)
461-
return TryUnwrapEnum(sqlContainer);
462-
return body;
460+
return body is SqlContainer sqlContainer ? TryUnwrapEnum(sqlContainer) : body;
463461
}
464462

465463
protected override SqlExpression VisitNew(NewExpression n)

Orm/Xtensive.Orm/Orm/Rse/AggregateType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Xtensive.Orm.Rse
99
/// <summary>
1010
/// Defines the set of aggregate functions.
1111
/// </summary>
12-
public enum AggregateType
12+
public enum AggregateType : byte
1313
{
1414
/// <summary>
1515
/// Average of the values in a column.
@@ -36,4 +36,4 @@ public enum AggregateType
3636
/// </summary>
3737
Sum = 4
3838
}
39-
}
39+
}

Orm/Xtensive.Orm/Orm/Rse/Transformation/ColumnMappingInspector.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,21 @@ internal protected override PredicateJoinProvider VisitPredicateJoin(PredicateJo
158158
{
159159
var (leftMapping, rightMapping) = SplitMappings(provider);
160160

161-
leftMapping.AddRange(mappingsGatherer.Gather(provider.Predicate,
162-
provider.Predicate.Parameters[0]));
163-
rightMapping.AddRange(mappingsGatherer.Gather(provider.Predicate,
164-
provider.Predicate.Parameters[1]));
161+
var providerPredicate = provider.Predicate;
162+
var providerPredicateParameters = providerPredicate.Parameters;
163+
leftMapping.AddRange(mappingsGatherer.Gather(providerPredicate,
164+
providerPredicateParameters[0]));
165+
rightMapping.AddRange(mappingsGatherer.Gather(providerPredicate,
166+
providerPredicateParameters[1]));
165167

166168
var newLeftProvider = provider.Left;
167169
var newRightProvider = provider.Right;
168170
VisitJoin(ref leftMapping, ref newLeftProvider, ref rightMapping, ref newRightProvider, false);
169171
mappings[provider] = MergeMappings(provider.Left, leftMapping, rightMapping);
170-
var predicate = TranslateJoinPredicate(leftMapping, rightMapping, provider.Predicate);
172+
var predicate = TranslateJoinPredicate(leftMapping, rightMapping, providerPredicate);
171173

172174
return newLeftProvider == provider.Left && newRightProvider == provider.Right
173-
&& provider.Predicate == predicate
175+
&& providerPredicate == predicate
174176
? provider
175177
: new PredicateJoinProvider(newLeftProvider, newRightProvider, (Expression<Func<Tuple, Tuple, bool>>) predicate, provider.JoinType);
176178
}
@@ -508,10 +510,11 @@ private Expression TranslateLambda(IReadOnlyList<ColNum> colMap, LambdaExpressio
508510
private Expression TranslateJoinPredicate(IReadOnlyList<ColNum> leftMapping,
509511
IReadOnlyList<ColNum> rightMapping, Expression<Func<Tuple, Tuple, bool>> expression)
510512
{
513+
var expressionParameters = expression.Parameters;
511514
var result = new TupleAccessRewriter(leftMapping, ResolveOuterMapping, true).Rewrite(expression,
512-
expression.Parameters[0]);
515+
expressionParameters[0]);
513516
return new TupleAccessRewriter(rightMapping, ResolveOuterMapping, true).Rewrite(result,
514-
expression.Parameters[1]);
517+
expressionParameters[1]);
515518
}
516519

517520
private void VisitJoin(

0 commit comments

Comments
 (0)