Skip to content

Commit cc5c051

Browse files
authored
Optmization: avoid intermediate Pair<ColNum> array (#217)
1 parent 82dce6f commit cc5c051

File tree

5 files changed

+18
-37
lines changed

5 files changed

+18
-37
lines changed

Orm/Xtensive.Orm/Orm/Internals/EntityDataReader.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class EntityDataReader : DomainBound
2222
private readonly record struct RecordPartMapping
2323
(
2424
int TypeIdColumnIndex,
25-
IReadOnlyList<Pair<ColNum>> Columns,
25+
IEnumerable<(ColNum From, ColNum To)> Columns,
2626
TypeInfo ApproximateType
2727
);
2828

@@ -47,7 +47,7 @@ public IEnumerable<Record> Read(IEnumerable<Tuple> source, RecordSetHeader heade
4747
for (int i = 0; i < recordPartCount; i++) {
4848
var columnGroup = columnGroups[i];
4949
var approximateType = columnGroup.TypeInfoRef.Resolve(model);
50-
var columnMapping = new List<Pair<ColNum>>(columnGroup.Columns.Count);
50+
var columnMapping = new List<(ColNum From, ColNum To)>(columnGroup.Columns.Count);
5151
var typeIdColumnIndex = -1;
5252
foreach (var columnIndex in columnGroup.Columns) {
5353
var column = (MappedColumn) columns[columnIndex];
@@ -57,7 +57,7 @@ public IEnumerable<Record> Read(IEnumerable<Tuple> source, RecordSetHeader heade
5757
if (columnInfo.Name == typeIdColumnName) {
5858
typeIdColumnIndex = column.Index;
5959
}
60-
columnMapping.Add(new Pair<ColNum>(targetColumnIndex, columnIndex));
60+
columnMapping.Add((targetColumnIndex, columnIndex));
6161
}
6262
}
6363
mappings[i] = new RecordPartMapping(typeIdColumnIndex, columnMapping, approximateType);

Orm/Xtensive.Orm/Orm/Linq/Materialization/ExpressionMaterializer.cs

+5-13
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,7 @@ protected override Expression VisitStructureFieldExpression(StructureFieldExpres
248248
var mappingInfo = expression.Fields
249249
.OfType<FieldExpression>()
250250
.Where(f => f.ExtendedType==ExtendedExpressionType.Field)
251-
.OrderBy(f => f.Field.MappingInfo.Offset)
252-
.Select(f => new Pair<ColNum>(f.Field.MappingInfo.Offset, f.Mapping.Offset))
253-
.Distinct()
254-
.ToArray();
251+
.Select(f => (f.Field.MappingInfo.Offset, f.Mapping.Offset));
255252

256253
var columnMap = MaterializationHelper.CreateSingleSourceMap(tuplePrototype.Count, mappingInfo);
257254

@@ -296,11 +293,8 @@ protected override Expression VisitStructureExpression(StructureExpression expre
296293
var tuplePrototype = typeInfo.TuplePrototype;
297294
var mappingInfo = expression.Fields
298295
.OfType<FieldExpression>()
299-
.Where(f => f.ExtendedType==ExtendedExpressionType.Field)
300-
.OrderBy(f => f.Field.MappingInfo.Offset)
301-
.Select(f => new Pair<ColNum>(f.Field.MappingInfo.Offset, f.Mapping.Offset))
302-
.Distinct()
303-
.ToArray();
296+
.Where(f => f.ExtendedType==ExtendedExpressionType.Field)
297+
.Select(f => (f.Field.MappingInfo.Offset, f.Mapping.Offset));
304298

305299
var columnMap = MaterializationHelper.CreateSingleSourceMap(tuplePrototype.Count, mappingInfo);
306300

@@ -362,10 +356,8 @@ private Expression CreateEntity(IEntityExpression expression, Expression tupleEx
362356
var mappingInfo = expression.Fields
363357
.OfType<FieldExpression>()
364358
.Where(f => f.ExtendedType==ExtendedExpressionType.Field)
365-
.OrderBy(f => f.Field.MappingInfo.Offset)
366-
.Select(f => new Pair<ColNum>(f.Field.MappingInfo.Offset, f.Mapping.Offset))
367-
.Distinct()
368-
.ToArray();
359+
.Select(f => (f.Field.MappingInfo.Offset, f.Mapping.Offset))
360+
.ToHashSet();
369361

370362
var isMaterializedExpression = Expression.Call(
371363
itemMaterializationContextParameter,

Orm/Xtensive.Orm/Orm/Linq/Materialization/ItemMaterializationContext.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the License.txt file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
67
using System.Reflection;
78
using Xtensive.Core;
89
using Xtensive.Orm.Internals;
@@ -34,7 +35,7 @@ internal sealed class ItemMaterializationContext
3435

3536
public TypeInfo GetTypeInfo(int typeId) => typeId == TypeInfo.NoTypeId ? null : typeIdRegistry[typeId];
3637

37-
public Entity Materialize(int entityIndex, int typeIdIndex, TypeInfo type, Pair<ColNum>[] entityColumns, Tuple tuple)
38+
public Entity Materialize(int entityIndex, int typeIdIndex, TypeInfo type, IEnumerable<(ColNum From, ColNum To)> entityColumns, Tuple tuple)
3839
{
3940
var result = entities[entityIndex];
4041
if (result!=null)

Orm/Xtensive.Orm/Orm/Linq/Materialization/MaterializationContext.cs

+5-12
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public TypeIdRegistry TypeIdRegistry
5858
/// </summary>
5959
public Queue<Action> MaterializationQueue { get; set; }
6060

61-
public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int typeId, IReadOnlyList<Pair<ColNum>> columns)
61+
public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int typeId, IEnumerable<(ColNum From, ColNum To)> columns)
6262
{
6363
ref var cache = ref entityMappings[entityIndex];
6464
if (cache.SingleItem is TypeMapping result) {
@@ -73,19 +73,12 @@ public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int
7373
var keyInfo = type.Key;
7474
var descriptor = type.TupleDescriptor;
7575

76-
var typeColumnMap = columns;
76+
IEnumerable<(ColNum From, ColNum To)> typeColumnMap = columns;
7777
if (approximateType.IsInterface) {
7878
// fixup target index
79-
var newColumns = new Pair<ColNum>[columns.Count];
80-
for (int i = columns.Count; i-- > 0;) {
81-
var pair = columns[i];
82-
var approxTargetIndex = pair.First;
83-
var interfaceField = approximateType.Columns[approxTargetIndex].Field;
84-
var field = type.FieldMap[interfaceField];
85-
var targetIndex = field.MappingInfo.Offset;
86-
newColumns[i] = new Pair<ColNum>(targetIndex, pair.Second);
87-
}
88-
typeColumnMap = newColumns;
79+
var fieldMap = type.FieldMap;
80+
var approximateTypeColumns = approximateType.Columns;
81+
typeColumnMap = columns.Select(p => (fieldMap[approximateTypeColumns[p.From].Field].MappingInfo.Offset, p.To));
8982
}
9083

9184
var allIndexes = MaterializationHelper.CreateSingleSourceMap(descriptor.Count, typeColumnMap);

Orm/Xtensive.Orm/Orm/Linq/Materialization/MaterializationHelper.cs

+3-8
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,13 @@ internal static class MaterializationHelper
4343
public static readonly MethodInfo PrefetchEntitySetMethodInfo = typeof(MaterializationHelper)
4444
.GetMethod(nameof(PrefetechEntitySet), BindingFlags.Public | BindingFlags.Static);
4545

46-
public static ColNum[] CreateSingleSourceMap(int targetLength, IReadOnlyList<Pair<ColNum>> remappedColumns)
46+
public static ColNum[] CreateSingleSourceMap(int targetLength, IEnumerable<(ColNum From, ColNum To)> remappedColumns)
4747
{
4848
var map = new ColNum[targetLength];
4949
Array.Fill(map, MapTransform.NoMapping);
50-
51-
for (int i = 0, count = remappedColumns.Count; i < count; i++) {
52-
var remappedColumn = remappedColumns[i];
53-
var targetIndex = remappedColumn.First;
54-
var sourceIndex = remappedColumn.Second;
55-
map[targetIndex] = sourceIndex;
50+
foreach (var p in remappedColumns) {
51+
map[p.From] = p.To;
5652
}
57-
5853
return map;
5954
}
6055

0 commit comments

Comments
 (0)