From 930a40dfe535e2d1ae9b81c4cd321172239f0abf Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Wed, 21 May 2025 15:23:56 -0700 Subject: [PATCH] Optimize `FieldExpression` construction --- .../Orm/Linq/Expressions/EntityExpression.cs | 30 ++++--------------- .../Linq/Expressions/EntityFieldExpression.cs | 8 +++-- .../Orm/Linq/Expressions/FieldExpression.cs | 4 +-- .../Expressions/StructureFieldExpression.cs | 25 +++++++--------- 4 files changed, 23 insertions(+), 44 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityExpression.cs index a15c634f4a..5742139a6a 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityExpression.cs @@ -4,9 +4,6 @@ // Created by: Alexis Kochetov // Created: 2009.05.05 -using System; -using System.Linq; -using System.Collections.Generic; using System.Linq.Expressions; using Xtensive.Orm.Model; using Xtensive.Orm.Linq.Expressions.Visitors; @@ -184,26 +181,11 @@ public static EntityExpression Create(EntityFieldExpression entityFieldExpressio entityFieldExpression.OuterParameter, new Dictionary()); } - private static PersistentFieldExpression BuildNestedFieldExpression(FieldInfo nestedField, ColNum offset) - { - if (nestedField.IsPrimitive) { - return FieldExpression.CreateField(nestedField, offset); - } - - if (nestedField.IsStructure) { - return StructureFieldExpression.CreateStructure(nestedField, offset); - } - - if (nestedField.IsEntity) { - return EntityFieldExpression.CreateEntityField(nestedField, offset); - } - - if (nestedField.IsEntitySet) { - return EntitySetExpression.CreateEntitySet(nestedField); - } - - throw new NotSupportedException(string.Format(Strings.ExNestedFieldXIsNotSupported, nestedField.Attributes)); - } + private static PersistentFieldExpression BuildNestedFieldExpression(FieldInfo nestedField, ColNum offset) => + nestedField.IsStructure ? StructureFieldExpression.CreateStructure(nestedField, offset) + : nestedField.IsEntity ? EntityFieldExpression.CreateEntityField(nestedField, offset) + : nestedField.IsEntitySet ? EntitySetExpression.CreateEntitySet(nestedField) + : FieldExpression.CreateField(nestedField, offset); public override string ToString() => $"{base.ToString()} {PersistentType.Name}"; @@ -222,4 +204,4 @@ private EntityExpression( Key = key; } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityFieldExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityFieldExpression.cs index 80d280315c..79bfb7aabf 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityFieldExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/EntityFieldExpression.cs @@ -162,10 +162,12 @@ public static EntityFieldExpression CreateEntityField(FieldInfo entityField, Col var mapping = new Segment((ColNum) (mappingInfo.Offset + offset), mappingInfo.Length); var keyFields = persistentType.Key.Fields; var keyExpression = KeyExpression.Create(persistentType, (ColNum) (offset + mappingInfo.Offset)); - var fields = new List(keyFields.Count + 1) { keyExpression }; + var fields = new PersistentFieldExpression[keyFields.Count + 1]; + fields[0] = keyExpression; + int i = 1; foreach (var field in keyFields) { // Do not convert to LINQ. We want to avoid a closure creation here. - fields.Add(BuildNestedFieldExpression(field, (ColNum) (offset + mappingInfo.Offset))); + fields[i++] = BuildNestedFieldExpression(field, (ColNum) (offset + mappingInfo.Offset)); } return new EntityFieldExpression(persistentType, entityField, fields, mapping, keyExpression, null, null, false); @@ -205,4 +207,4 @@ private EntityFieldExpression( Entity = entity; } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/FieldExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/FieldExpression.cs index ab6f675beb..e92eb352a8 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/FieldExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/FieldExpression.cs @@ -4,8 +4,6 @@ // Created by: Alexis Kochetov // Created: 2009.05.05 -using System; -using System.Collections.Generic; using System.Linq.Expressions; using Xtensive.Core; using Xtensive.Orm.Linq.Expressions.Visitors; @@ -137,4 +135,4 @@ protected FieldExpression( Field = field; } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs index 9a4a8561ca..d4e6cb5f97 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs @@ -17,14 +17,14 @@ namespace Xtensive.Orm.Linq.Expressions internal sealed class StructureFieldExpression : FieldExpression, IPersistentExpression { - private List fields; + private IReadOnlyList fields; public TypeInfo PersistentType { get; } public bool IsNullable => Owner != null && Owner.IsNullable; public IReadOnlyList Fields => fields; - private void SetFields(List value) + private void SetFields(IReadOnlyList value) { fields = value; foreach (var fieldExpression in fields.OfType()) { @@ -103,10 +103,11 @@ public override StructureFieldExpression BindParameter(ParameterExpression param var result = new StructureFieldExpression(PersistentType, Field, Mapping, OuterParameter, DefaultIfEmpty); processedExpressions.Add(this, result); - var processedFields = new List(fields.Count); + var processedFields = new PersistentFieldExpression[fields.Count]; + int i = 0; foreach (var field in fields) { // Do not convert to LINQ. We want to avoid a closure creation here. - processedFields.Add((PersistentFieldExpression) field.BindParameter(parameter, processedExpressions)); + processedFields[i++] = (PersistentFieldExpression) field.BindParameter(parameter, processedExpressions); } if (Owner == null) { @@ -127,10 +128,11 @@ public override Expression RemoveOuterParameter(Dictionary(fields.Count); + var processedFields = new PersistentFieldExpression[fields.Count]; + int i = 0; foreach (var field in fields) { // Do not convert to LINQ. We want to avoid a closure creation here. - processedFields.Add((PersistentFieldExpression) field.RemoveOuterParameter(processedExpressions)); + processedFields[i++] = (PersistentFieldExpression) field.RemoveOuterParameter(processedExpressions); } if (Owner == null) { @@ -149,14 +151,9 @@ public override FieldExpression RemoveOwner() return this; } - var result = new StructureFieldExpression(PersistentType, Field, Mapping, OuterParameter, DefaultIfEmpty) { - fields = new List(fields.Count) + return new StructureFieldExpression(PersistentType, Field, Mapping, OuterParameter, DefaultIfEmpty) { + fields = fields.Select(o => ((FieldExpression) o).RemoveOwner()).ToArray() }; - foreach (var field in fields) { - result.fields.Add(((FieldExpression) field).RemoveOwner()); - } - - return result; } public static StructureFieldExpression CreateStructure(FieldInfo structureField, ColNum offset) @@ -213,4 +210,4 @@ private StructureFieldExpression( PersistentType = persistentType; } } -} \ No newline at end of file +}