From 6cb22cf3577fe4699229e0910b989571391df653 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Wed, 13 May 2026 13:26:59 -0700 Subject: [PATCH] Optimization: Use `CollectionsMarshal.GetValueRefOrAddDefault()` for Dictionary operations --- Orm/Xtensive.Orm/IoC/ServiceContainer.cs | 7 ++-- .../Modelling/Comparison/Hints/HintSet.cs | 14 +++----- .../Orm/Building/Builders/ModelBuilder.cs | 35 ++++++++++--------- .../NonPairedReferenceChangesRegistry.cs | 30 ++++++++-------- .../Caching/SessionCachingSequenceProvider.cs | 13 +++---- .../Internals/Prefetch/Nodes/ExpressionMap.cs | 17 +++++---- .../ReferentialIntegrity/RemovalContext.cs | 16 ++++----- .../Expressions/LocalCollectionExpression.cs | 24 ++++++------- .../Expressions/StructureFieldExpression.cs | 15 ++++---- .../Orm/Linq/TranslatorContext.cs | 19 ++++------ Orm/Xtensive.Orm/Orm/Model/FieldMap.cs | 12 +++---- .../ExpressionProcessor.Helpers.cs | 11 ++---- .../Requests/PersistRequestBuilder.cs | 9 ++--- .../Internals/CalculateProviderCollector.cs | 13 +++---- 14 files changed, 104 insertions(+), 131 deletions(-) diff --git a/Orm/Xtensive.Orm/IoC/ServiceContainer.cs b/Orm/Xtensive.Orm/IoC/ServiceContainer.cs index 55acc79e3e..8dc9b5b741 100644 --- a/Orm/Xtensive.Orm/IoC/ServiceContainer.cs +++ b/Orm/Xtensive.Orm/IoC/ServiceContainer.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Reflection; +using System.Runtime.InteropServices; using Xtensive.Collections; using Xtensive.Core; using Xtensive.Reflection; @@ -120,10 +121,8 @@ private object GetOrCreateInstance(ServiceRegistration registration) => private static void Register(Dictionary> types, ServiceRegistration serviceRegistration) { var key = GetKey(serviceRegistration.Type, serviceRegistration.Name); - if (!types.TryGetValue(key, out var list)) { - types[key] = list = new List(1); - } - list.Add(serviceRegistration); + ref var list = ref CollectionsMarshal.GetValueRefOrAddDefault(types, key, out var exists); + (exists ? list : (list = new(1))).Add(serviceRegistration); } #endregion diff --git a/Orm/Xtensive.Orm/Modelling/Comparison/Hints/HintSet.cs b/Orm/Xtensive.Orm/Modelling/Comparison/Hints/HintSet.cs index 946c4690bc..7d8df949bb 100644 --- a/Orm/Xtensive.Orm/Modelling/Comparison/Hints/HintSet.cs +++ b/Orm/Xtensive.Orm/Modelling/Comparison/Hints/HintSet.cs @@ -4,13 +4,9 @@ // Created by: Alex Yakunin // Created: 2009.03.26 -using System; using System.Collections; -using System.Collections.Generic; using System.Diagnostics; -using System.Reflection; -using Xtensive.Collections; -using System.Linq; +using System.Runtime.InteropServices; using Xtensive.Core; namespace Xtensive.Modelling.Comparison.Hints @@ -165,10 +161,8 @@ private Dictionary GetNodeHints(Node node) { ArgumentNullException.ThrowIfNull(node); - if (!hintMap.TryGetValue(node, out var nodeHintMap)) { - hintMap.Add(node, nodeHintMap = new Dictionary()); - } - return nodeHintMap; + ref var nodeHintMap = ref CollectionsMarshal.GetValueRefOrAddDefault(hintMap, node, out var exists); + return exists ? nodeHintMap : (nodeHintMap = new()); } #region ILockable methods @@ -214,4 +208,4 @@ private HintSet() { } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs b/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs index ff8089a34c..f98d060972 100644 --- a/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs +++ b/Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs @@ -4,10 +4,9 @@ // Created by: Dmitri Maximov // Created: 2007.09.26 -using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Xtensive.Core; using Xtensive.Orm.Building.Definitions; using Xtensive.Orm.Building.DependencyGraph; @@ -242,12 +241,8 @@ private void PreprocessAssociations() if (paired.Item1.TargetType.IsInterface || typesWithProcessedInheritedAssociations.Contains(paired.Item1.TargetType)) AssociationBuilder.BuildReversedAssociation(context, paired.Item1, paired.Item2); else { - List<(AssociationInfo, string)> pairs; - if (!pairedAssociationsToReverse.TryGetValue(paired.Item1.TargetType, out pairs)) { - pairs = new List<(AssociationInfo, string)>(); - pairedAssociationsToReverse.Add(paired.Item1.TargetType, pairs); - } - pairs.Add(paired); + ref var pairs = ref CollectionsMarshal.GetValueRefOrAddDefault(pairedAssociationsToReverse, paired.Item1.TargetType, out var exists); + (exists ? pairs : (pairs = new(1))).Add(paired); } } continue; @@ -483,17 +478,25 @@ private void RegiserReferences(Dictionary referenceRegistrator, p var typeImplementors = type.DirectImplementors; var descendantTypes = type.AllDescendants; if (typeImplementors.Any()) { - foreach (var implementor in typeImplementors) - if (referenceRegistrator.TryGetValue(implementor, out var refCount)) - referenceRegistrator[implementor] = refCount + 1; + foreach (var implementor in typeImplementors) { + ref var refCount = ref CollectionsMarshal.GetValueRefOrNullRef(referenceRegistrator, implementor); + if (!Unsafe.IsNullRef(ref refCount)) { + ++refCount; + } + } } else { - if (referenceRegistrator.TryGetValue(type, out var refCount)) - referenceRegistrator[type] = refCount + 1; + ref var refCount = ref CollectionsMarshal.GetValueRefOrNullRef(referenceRegistrator, type); + if (!Unsafe.IsNullRef(ref refCount)) { + ++refCount; + } + if (descendantTypes.Any()) { foreach (var descendant in descendantTypes) { - if (referenceRegistrator.TryGetValue(descendant, out var refCount1)) - referenceRegistrator[descendant] = refCount1 + 1; + ref var refCount1 = ref CollectionsMarshal.GetValueRefOrNullRef(referenceRegistrator, descendant); + if (!Unsafe.IsNullRef(ref refCount1)) { + ++refCount1; + } } } } diff --git a/Orm/Xtensive.Orm/Orm/Internals/ChangeRegistries/NonPairedReferenceChangesRegistry.cs b/Orm/Xtensive.Orm/Orm/Internals/ChangeRegistries/NonPairedReferenceChangesRegistry.cs index 85d7f0e8f6..d2f94fd2e1 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/ChangeRegistries/NonPairedReferenceChangesRegistry.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/ChangeRegistries/NonPairedReferenceChangesRegistry.cs @@ -4,10 +4,7 @@ // Created by: Alexey Kulakov // Created: 2016.06.21 -using System; -using System.Collections.Generic; -using System.Linq; -using Xtensive.Core; +using System.Runtime.InteropServices; using Xtensive.Orm.Model; namespace Xtensive.Orm.Internals @@ -43,8 +40,8 @@ public Identifier(EntityState entityState, AssociationInfo association) } } - private readonly IDictionary> removedReferences = new Dictionary>(); - private readonly IDictionary> addedReferences = new Dictionary>(); + private readonly Dictionary> removedReferences = new(); + private readonly Dictionary> addedReferences = new(); private readonly object accessGuard = new(); internal Session Session { get; } @@ -125,14 +122,17 @@ private void RegisterRemoveInternal(Identifier oldKey, EntityState referencingSt return; } } - if (removedReferences.TryGetValue(oldKey, out var renivedRefs)) { + + ref var renivedRefs = ref CollectionsMarshal.GetValueRefOrAddDefault(removedReferences, oldKey, out var exists); + if (exists) { if (!renivedRefs.Add(referencingState)) { throw new InvalidOperationException(Strings.ExReferenceRregistrationErrorReferenceRemovalIsAlreadyRegistered); } - return; } - EnsureRegistrationsAllowed(); - removedReferences.Add(oldKey, new HashSet{referencingState}); + else { + EnsureRegistrationsAllowed(); + renivedRefs = [referencingState]; + } } private void RegisterAddInternal(Identifier newKey, EntityState referencingState) @@ -146,14 +146,16 @@ private void RegisterAddInternal(Identifier newKey, EntityState referencingState } return; } - if (addedReferences.TryGetValue(newKey, out var addedRefs)) { + ref var addedRefs = ref CollectionsMarshal.GetValueRefOrAddDefault(addedReferences, newKey, out var exists); + if (exists) { if (!addedRefs.Add(referencingState)) { throw new InvalidOperationException(Strings.ExReferenceRegistrationErrorReferenceAdditionIsAlreadyRegistered); } - return; } - EnsureRegistrationsAllowed(); - addedReferences.Add(newKey, new HashSet{referencingState}); + else { + EnsureRegistrationsAllowed(); + addedRefs = [referencingState]; + } } private void Initialize() diff --git a/Orm/Xtensive.Orm/Orm/Internals/KeyGenerators/Caching/SessionCachingSequenceProvider.cs b/Orm/Xtensive.Orm/Orm/Internals/KeyGenerators/Caching/SessionCachingSequenceProvider.cs index ff396abf49..3d1648a49e 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/KeyGenerators/Caching/SessionCachingSequenceProvider.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/KeyGenerators/Caching/SessionCachingSequenceProvider.cs @@ -4,9 +4,7 @@ // Created by: Denis Krjuchkov // Created: 2012.05.17 -using System; -using System.Collections.Generic; -using Xtensive.Core; +using System.Runtime.InteropServices; using Xtensive.Orm.Model; using Xtensive.Orm.Providers; @@ -20,11 +18,8 @@ private sealed class CachingSequenceCollection public CachingSequence GetSequence(SequenceInfo sequenceInfo, IStorageSequenceAccessor accessor) { - if (!sequences.TryGetValue(sequenceInfo, out var result)) { - result = new CachingSequence(accessor, false); - sequences.Add(sequenceInfo, result); - } - return result; + ref var result = ref CollectionsMarshal.GetValueRefOrAddDefault(sequences, sequenceInfo, out var exists); + return exists ? result : (result = new(accessor, false)); } private void OnTransactionRollbacked(object sender, TransactionEventArgs e) @@ -62,4 +57,4 @@ public SessionCachingSequenceProvider(IStorageSequenceAccessor accessor) this.accessor = accessor; } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ExpressionMap.cs b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ExpressionMap.cs index 50d7ed2c89..39d356a9e5 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ExpressionMap.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/Prefetch/Nodes/ExpressionMap.cs @@ -4,10 +4,8 @@ // Created by: Denis Krjuchkov // Created: 2012.02.24 -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; -using Xtensive.Collections; +using System.Runtime.InteropServices; namespace Xtensive.Orm.Internals.Prefetch { @@ -26,12 +24,13 @@ public IEnumerable GetChildren(Expression parent) public void RegisterChild(Expression parent, Expression child) { - HashSet children; - if (!childrenMap.TryGetValue(parent, out children)) { - children = new HashSet(); - childrenMap.Add(parent, children); + ref var children = ref CollectionsMarshal.GetValueRefOrAddDefault(childrenMap, parent, out var exists); + if (exists) { + children.Add(child); + } + else { + children = [child]; } - children.Add(child); } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Internals/ReferentialIntegrity/RemovalContext.cs b/Orm/Xtensive.Orm/Orm/Internals/ReferentialIntegrity/RemovalContext.cs index 9c050a3ad5..7ee056775b 100644 --- a/Orm/Xtensive.Orm/Orm/Internals/ReferentialIntegrity/RemovalContext.cs +++ b/Orm/Xtensive.Orm/Orm/Internals/ReferentialIntegrity/RemovalContext.cs @@ -4,11 +4,9 @@ // Created by: Dmitri Maximov // Created: 2008.07.02 -using System; -using System.Collections.Generic; +using System.Runtime.InteropServices; using Xtensive.Core; using Xtensive.Orm.Model; -using System.Linq; namespace Xtensive.Orm.ReferentialIntegrity { @@ -68,12 +66,12 @@ public void Enqueue(Entity entity, EntityRemoveReason reason) else { types.Enqueue(type); } - if (queue.TryGetValue(type, out var set)) { + ref var set = ref CollectionsMarshal.GetValueRefOrAddDefault(queue, type, out var exists); + if (exists) { _ = set.Add(entity); } else { - set = new HashSet { entity }; - queue.Add(type, set); + set = [entity]; } removeReasons[entity] = reason; @@ -92,10 +90,8 @@ public void Enqueue(IEnumerable entities, EntityRemoveReason reason) types.Enqueue(type); } - if (!queue.TryGetValue(type, out var set1)) { - set1 = new HashSet(); - queue.Add(type, set1); - } + ref var set1Ref = ref CollectionsMarshal.GetValueRefOrAddDefault(queue, type, out var exists); + var set1 = exists ? set1Ref : (set1Ref = []); foreach (var entity in group) { removeReasons[entity] = reason; _ = set1.Add(entity); diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/LocalCollectionExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/LocalCollectionExpression.cs index 4ad22edeb1..8f2dd56b50 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/LocalCollectionExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/LocalCollectionExpression.cs @@ -4,13 +4,9 @@ // Created by: Alexey Gamzov // Created: 2009.09.09 -using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Xtensive.Collections; -using Xtensive.Core; +using System.Runtime.InteropServices; using Xtensive.Orm.Linq.Expressions.Visitors; namespace Xtensive.Orm.Linq.Expressions @@ -56,22 +52,25 @@ public override Expression Remap(ColumnMap map, Dictionary processedExpressions) { - if (processedExpressions.TryGetValue(this, out var value)) - return (ParameterizedExpression) value; - + ref var resultRef = ref CollectionsMarshal.GetValueRefOrAddDefault(processedExpressions, this, out var exists); + if (exists) { + return (ParameterizedExpression) resultRef; + } var result = new LocalCollectionExpression(Type, MemberInfo, expressionAsString); - processedExpressions.Add(this, result); + resultRef = result; result.Fields = Fields.ToDictionary(f=>f.Key, f=>(IMappedExpression)f.Value.BindParameter(parameter, processedExpressions)); return result; } public override Expression RemoveOuterParameter(Dictionary processedExpressions) { - if (processedExpressions.TryGetValue(this, out var value)) - return value; + ref var resultRef = ref CollectionsMarshal.GetValueRefOrAddDefault(processedExpressions, this, out var exists); + if (exists) { + return resultRef; + } var result = new LocalCollectionExpression(Type, MemberInfo, expressionAsString); - processedExpressions.Add(this, result); + resultRef = result; result.Fields = Fields.ToDictionary(f=>f.Key, f=>(IMappedExpression)f.Value.RemoveOuterParameter(processedExpressions)); return result; } @@ -84,7 +83,6 @@ public LocalCollectionExpression(Type type, MemberInfo memberInfo, Expression so Fields = new Dictionary(); MemberInfo = memberInfo; expressionAsString = sourceExpression.ToString(); - ; } internal override Expression Accept(ExtendedExpressionVisitor visitor) => visitor.VisitLocalCollectionExpression(this); diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs index c161bbca8b..2ec6b7c086 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/StructureFieldExpression.cs @@ -5,6 +5,7 @@ // Created: 2009.05.05 using System.Linq.Expressions; +using System.Runtime.InteropServices; using Xtensive.Core; using Xtensive.Orm.Model; using Xtensive.Orm.Linq.Expressions.Visitors; @@ -95,12 +96,13 @@ public override StructureFieldExpression Remap(ColumnMap map, Dictionary processedExpressions) { - if (processedExpressions.TryGetValue(this, out var value)) { - return (StructureFieldExpression)value; + ref var resultRef = ref CollectionsMarshal.GetValueRefOrAddDefault(processedExpressions, this, out var exists); + if (exists) { + return (StructureFieldExpression) resultRef; } var result = new StructureFieldExpression(PersistentType, Field, Mapping, OuterParameter, DefaultIfEmpty); - processedExpressions.Add(this, result); + resultRef = result; var processedFields = new PersistentFieldExpression[fields.Count]; int i = 0; foreach (var field in fields) { @@ -120,12 +122,13 @@ public override StructureFieldExpression BindParameter(ParameterExpression param public override StructureFieldExpression RemoveOuterParameter(Dictionary processedExpressions) { - if (processedExpressions.TryGetValue(this, out var value)) { - return (StructureFieldExpression) value; + ref var resultRef = ref CollectionsMarshal.GetValueRefOrAddDefault(processedExpressions, this, out var exists); + if (exists) { + return (StructureFieldExpression) resultRef; } var result = new StructureFieldExpression(PersistentType, Field, Mapping, OuterParameter, DefaultIfEmpty); - processedExpressions.Add(this, result); + resultRef = result; var processedFields = new PersistentFieldExpression[fields.Count]; int i = 0; foreach (var field in fields) { diff --git a/Orm/Xtensive.Orm/Orm/Linq/TranslatorContext.cs b/Orm/Xtensive.Orm/Orm/Linq/TranslatorContext.cs index 48eec5b40d..40bd562afa 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/TranslatorContext.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/TranslatorContext.cs @@ -7,6 +7,7 @@ using System.Text; using System.Linq.Expressions; using System.Reflection; +using System.Runtime.InteropServices; using Xtensive.Core; using Xtensive.Orm.Internals; using Xtensive.Orm.Linq.Expressions; @@ -68,13 +69,13 @@ internal sealed class TranslatorContext public ApplyParameter GetApplyParameter(CompilableProvider provider) { - if (!applyParameters.TryGetValue(provider, out var parameter)) { + ref var parameter = ref CollectionsMarshal.GetValueRefOrAddDefault(applyParameters, provider, out var exists); + if (!exists) { var providerType = provider.GetType(); parameter = new ApplyParameter(providerType.IsGenericType ? providerType.GetShortName() : providerType.Name); // parameter = new ApplyParameter(provider.ToString()); // ENABLE ONLY FOR DEBUGGING! // May lead TO entity.ToString() calls, while ToString can be overridden. - applyParameters.Add(provider, parameter); } return parameter; } @@ -110,20 +111,14 @@ public void RebindApplyParameter(CompilableProvider old, CompilableProvider @new public Parameter GetTupleParameter(ParameterExpression expression) { - if (!tupleParameters.TryGetValue(expression, out var parameter)) { - parameter = new Parameter(expression.ToString()); - tupleParameters.Add(expression, parameter); - } - return parameter; + ref var parameter = ref CollectionsMarshal.GetValueRefOrAddDefault(tupleParameters, expression, out var exists); + return exists ? parameter : (parameter = new(expression.ToString())); } public ItemProjectorExpression GetBoundItemProjector(ParameterExpression parameter, ItemProjectorExpression itemProjector) { - if (!boundItemProjectors.TryGetValue(parameter, out var result)) { - result = itemProjector.BindOuterParameter(parameter); - boundItemProjectors.Add(parameter, result); - } - return result; + ref var result = ref CollectionsMarshal.GetValueRefOrAddDefault(boundItemProjectors, parameter, out var exists); + return exists ? result : (result = itemProjector.BindOuterParameter(parameter)); } public void RegisterPossibleQueryReuse(MemberInfo memberInfo) diff --git a/Orm/Xtensive.Orm/Orm/Model/FieldMap.cs b/Orm/Xtensive.Orm/Orm/Model/FieldMap.cs index df53bcda7f..1b5aeeffc1 100644 --- a/Orm/Xtensive.Orm/Orm/Model/FieldMap.cs +++ b/Orm/Xtensive.Orm/Orm/Model/FieldMap.cs @@ -4,10 +4,8 @@ // Created by: Alexey Kochetov // Created: 2007.12.27 -using System; using System.Collections; -using System.Collections.Generic; -using System.Linq; +using System.Runtime.InteropServices; using Xtensive.Core; namespace Xtensive.Orm.Model @@ -52,11 +50,13 @@ internal bool TryAdd(FieldInfo interfaceField, FieldInfo typeField) if (!map.TryAdd(interfaceField, typeField)) { return false; } - if (reversedMap.TryGetValue(typeField, out var interfaceFields)) { + ref var interfaceFields = ref CollectionsMarshal.GetValueRefOrAddDefault(reversedMap, typeField, out var exists); + if (exists) { interfaceFields.Add(interfaceField); } - else - reversedMap.Add(typeField, new HashSet { interfaceField }); + else { + interfaceFields = [interfaceField]; + } return true; } diff --git a/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.Helpers.cs b/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.Helpers.cs index 316537de92..8fd94639a3 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.Helpers.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.Helpers.cs @@ -4,12 +4,11 @@ // Created by: Denis Krjuchkov // Created: 2009.09.26 -using System; using System.Linq.Expressions; +using System.Runtime.InteropServices; using System.Reflection; using Xtensive.Core; using Xtensive.Orm.Internals; -using Xtensive.Orm.Linq; using Xtensive.Reflection; using Xtensive.Sql; using Xtensive.Sql.Dml; @@ -334,12 +333,8 @@ private QueryParameterBinding RegisterParameterBinding(TypeMapping mapping, return result; } - if (bindingsWithIdentity.TryGetValue(identity.Value, out result)) - return result; - - result = new QueryParameterBinding(mapping, accessor.CachingCompile(), bindingType); - bindingsWithIdentity.Add(identity.Value, result); - return result; + ref var resultRef = ref CollectionsMarshal.GetValueRefOrAddDefault(bindingsWithIdentity, identity.Value, out var exists); + return exists ? resultRef : (resultRef = new QueryParameterBinding(mapping, accessor.CachingCompile(), bindingType)); } } } diff --git a/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs b/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs index 49b61fe3a7..d47afed512 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/Requests/PersistRequestBuilder.cs @@ -4,10 +4,7 @@ // Created by: Dmitri Maximov // Created: 2008.08.28 -using System; -using System.Collections.Generic; -using Xtensive.Core; -using Xtensive.Orm.Configuration; +using System.Runtime.InteropServices; using Xtensive.Orm.Model; using Xtensive.Sql; using Xtensive.Sql.Dml; @@ -207,11 +204,11 @@ private bool AddFakeVersionColumnUpdate(in PersistRequestBuilderContext context, private PersistParameterBinding GetBinding(PersistRequestBuilderContext context, ColumnInfo column, Table table, ColNum fieldIndex) { - if (!context.ParameterBindings.TryGetValue(column, out var binding)) { + ref var binding = ref CollectionsMarshal.GetValueRefOrAddDefault(context.ParameterBindings, column, out var exists); + if (!exists) { var typeMapping = driver.GetTypeMapping(column); var bindingType = GetTransmissionType(table.TableColumns[column.Name]); binding = new PersistParameterBinding(typeMapping, fieldIndex, bindingType); - context.ParameterBindings.Add(column, binding); } return binding; } diff --git a/Orm/Xtensive.Orm/Orm/Rse/Transformation/Internals/CalculateProviderCollector.cs b/Orm/Xtensive.Orm/Orm/Rse/Transformation/Internals/CalculateProviderCollector.cs index 8e2a71ba48..67c0503dd8 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Transformation/Internals/CalculateProviderCollector.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Transformation/Internals/CalculateProviderCollector.cs @@ -4,12 +4,9 @@ // Created by: Alexander Nikolaev // Created: 2009.05.22 -using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Runtime.CompilerServices; -using Xtensive.Core; +using System.Runtime.InteropServices; using Xtensive.Orm.Rse.Providers; using Tuple = Xtensive.Tuples.Tuple; @@ -34,12 +31,12 @@ public bool TryAdd(CalculateProvider provider) return false; var newPair = (provider, provider.Header.Columns); - if (owner.State.CalculateProviders.TryGetValue(applyParameter, out var existingList)) { - existingList.Add(newPair); + ref var list = ref CollectionsMarshal.GetValueRefOrAddDefault(owner.State.CalculateProviders, applyParameter, out var exists); + if (exists) { + list.Add(newPair); } else { - owner.State.CalculateProviders.Add(applyParameter, - new List<(CalculateProvider, ColumnCollection)> {newPair}); + list = [newPair]; } return true; }