Skip to content

Optimize BuildMaterializer() #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 8 additions & 20 deletions Orm/Xtensive.Orm/Orm/Internals/TypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,12 @@
using Xtensive.Tuples.Transform;
using Xtensive.Orm.Model;

namespace Xtensive.Orm.Internals
{
internal readonly struct TypeMapping
{
public readonly TypeInfo Type;
public readonly MapTransform KeyTransform;
public readonly IReadOnlyList<ColNum> KeyIndexes;
public readonly MapTransform Transform;
namespace Xtensive.Orm.Internals;


// Constructors

public TypeMapping(TypeInfo type, MapTransform keyTransform, MapTransform transform, IReadOnlyList<ColNum> keyIndexes)
{
Type = type;
KeyTransform = keyTransform;
Transform = transform;
KeyIndexes = keyIndexes;
}
}
}
internal readonly record struct TypeMapping
(
TypeInfo Type,
MapTransform KeyTransform,
MapTransform Transform,
IReadOnlyList<ColNum> KeyIndexes
);
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,11 @@ public TypeIdRegistry TypeIdRegistry

public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int typeId, IReadOnlyList<Pair<ColNum>> columns)
{
TypeMapping result;
ref var cache = ref entityMappings[entityIndex];
if (cache.SingleItem != null) {
if (typeId != ResolveTypeToNodeSpecificTypeIdentifier(cache.SingleItem?.Type)) {
throw new ArgumentOutOfRangeException("typeId");
}
return cache.SingleItem.Value;
if (cache.SingleItem is TypeMapping result) {
return typeId == ResolveTypeToNodeSpecificTypeIdentifier(result.Type)
? result
: throw new ArgumentOutOfRangeException("typeId");
}
if (cache.Items.TryGetValue(typeId, out result))
return result;
Expand All @@ -90,8 +88,8 @@ public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int
typeColumnMap = newColumns;
}

ArraySegment<ColNum> allIndexes = MaterializationHelper.CreateSingleSourceMap(descriptor.Count, typeColumnMap);
ArraySegment<ColNum> keyIndexes = allIndexes.Slice(0, keyInfo.TupleDescriptor.Count);
var allIndexes = MaterializationHelper.CreateSingleSourceMap(descriptor.Count, typeColumnMap);
var keyIndexes = allIndexes.Take(keyInfo.TupleDescriptor.Count).ToArray();

var transform = new MapTransform(true, descriptor, allIndexes);
var keyTransform = new MapTransform(true, keyInfo.TupleDescriptor, keyIndexes);
Expand Down
15 changes: 2 additions & 13 deletions Orm/Xtensive.Orm/Orm/Linq/Materialization/MaterializationInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@

using System.Linq.Expressions;

namespace Xtensive.Orm.Linq.Materialization
{
internal sealed class MaterializationInfo
{
public int EntitiesInRow { get; private set; }
public LambdaExpression Expression { get; private set; }
namespace Xtensive.Orm.Linq.Materialization;

public MaterializationInfo(int entitiesInRow, LambdaExpression expression)
{
EntitiesInRow = entitiesInRow;
Expression = expression;
}
}
}
internal readonly record struct MaterializationInfo(int EntitiesInRow, LambdaExpression Expression);
17 changes: 11 additions & 6 deletions Orm/Xtensive.Orm/Orm/Linq/Translator.Materialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,19 @@ private Materializer BuildMaterializer(ProjectionExpression projection, IReadOnl
var materializationInfo = itemProjector.Materialize(context, tupleParameters);
var elementType = itemProjector.Item.Type;
var materializeMethod = MaterializationHelper.MaterializeMethodInfo.CachedMakeGenericMethod(elementType);
var itemMaterializerFactoryMethod =
elementType.IsNullable()
? MaterializationHelper.CreateNullableItemMaterializerMethodInfo.CachedMakeGenericMethod(
elementType.GetGenericArguments()[0])

#if NET8_0_OR_GREATER
var itemMaterializerFactoryMethod = elementType.IsNullable()
? MaterializationHelper.CreateNullableItemMaterializerMethodInfo.CachedMakeGenericMethodInvoker(elementType.GetGenericArguments()[0])
: MaterializationHelper.CreateItemMaterializerMethodInfo.CachedMakeGenericMethodInvoker(elementType);
var itemMaterializer = itemMaterializerFactoryMethod.Invoke(null, materializationInfo.Expression, itemProjector.AggregateType);
#else
var itemMaterializerFactoryMethod = elementType.IsNullable()
? MaterializationHelper.CreateNullableItemMaterializerMethodInfo.CachedMakeGenericMethod(elementType.GetGenericArguments()[0])
: MaterializationHelper.CreateItemMaterializerMethodInfo.CachedMakeGenericMethod(elementType);
var itemMaterializer = itemMaterializerFactoryMethod.Invoke(null, [materializationInfo.Expression, itemProjector.AggregateType]);
#endif

var itemMaterializer = itemMaterializerFactoryMethod.Invoke(
null, new object[] { materializationInfo.Expression, itemProjector.AggregateType });
Expression<Func<Session, int, MaterializationContext>> materializationContextCtor =
(s, entityCount) => new MaterializationContext(s, entityCount);
var materializationContextExpression = materializationContextCtor
Expand Down
18 changes: 14 additions & 4 deletions Orm/Xtensive.Orm/Orm/Linq/TranslatorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,23 @@ public IReadOnlyList<string> GetMainQueryTags() =>
? applyParameters.Keys.OfType<TagProvider>().Select(p => p.Tag).ToList()
: Array.Empty<string>();

public IDisposable DisableSessionTags()
internal readonly struct TagsRestorer : IDisposable
{
var originalTags = SessionTags;
SessionTags = null;
return new Disposable((b) => SessionTags = originalTags);
private readonly TranslatorContext context;
private readonly IReadOnlyList<string> originalTags;

public void Dispose() => context.SessionTags = originalTags;

internal TagsRestorer(TranslatorContext context)
{
this.context = context;
originalTags = context.SessionTags;
context.SessionTags = null;
}
}

public TagsRestorer DisableSessionTags() => new(this);

public void RebindApplyParameter(CompilableProvider old, CompilableProvider @new)
{
if (applyParameters.TryGetValue(old, out var parameter)) {
Expand Down