dotnet / dotnet/efcore

Materializer optimizations

Open
#29,909 0 comments 0 reactions 0 assignees View on GitHub
area-perf area-query
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

As part of the AOT work (#25009), we now have a (hopefully) 100% faithful C# representation of the materializer expression tree (see code below).

Here are some quick perf fixes we can do:

* [ ] Remove the materializationContext creation when not needed:

```c#
var materializationContext1 = new MaterializationContext(ValueBuffer.Empty, queryContext0.Context);
```

* [ ] Eliminate the object array allocation and the boxing for non-composite key:

```c#
var entry1 = queryContext0.TryGetEntry(key, new object[]{(object)dataReader.GetInt32(0)}, true, out hasNullKey1);
```

* [ ] Avoid unneeded always-true entity type check:

```c#
entityType1 = entityType;
if (entityType1 == entityType)
```

* [ ] Avoid check for null entity type (when is this possible?):

```c#
entry1 = entityType1 == default(IEntityType) ? default(InternalEntityEntry) : queryContext0.StartTracking(entityType1, instance1, shadowValueBuffer1);
```

* [ ] Avoid explicitly setting instance to null, as it's already been initialized to null above:

```c#
else
{
instance1 = null;
}
```

* [ ] #21336
* [ ] #21334
* [ ] Consider the changes here: https://github.com/dotnet/efcore/pull/35128/files#r1846655927

### Code

```c#
IEntityType entityType1;
bool hasNullKey1;
var materializationContext1 = new MaterializationContext(ValueBuffer.Empty, queryContext0.Context);
Blog instance1 = null;
var entry1 = queryContext0.TryGetEntry(key, new object[]{(object)dataReader.GetInt32(0)}, true, out hasNullKey1);
if (!hasNullKey1)
{
if (entry1 != default(InternalEntityEntry))
{
entityType1 = entry1.EntityType;
instance1 = (Blog)entry1.Entity;
}
else
{
var shadowValueBuffer1 = ValueBuffer.Empty;
entityType1 = entityType;
if (entityType1 == entityType)
{
var instance0 = Activator.CreateInstance();
typeof(Blog).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance0, dataReader.GetInt32(0));
typeof(Blog).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance0, dataReader.GetString(1));
instance1 = instance0;
}
else
{
instance1 = null;
}

entry1 = entityType1 == default(IEntityType) ? default(InternalEntityEntry) : queryContext0.StartTracking(entityType1, instance1, shadowValueBuffer1);
}
}

var entity = instance1;
return entity;
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.