@@ -27,7 +27,7 @@ namespace Xtensive.Orm.Linq.Materialization
2727 internal class ExpressionMaterializer : PersistentExpressionVisitor
2828 {
2929 private const string RootQueryTagsPrefix = "Root query tags ->" ;
30-
30+ private const int NumberOfItemsOnStack = 64 ;
3131 private static readonly MethodInfo BuildPersistentTupleMethod = typeof ( ExpressionMaterializer ) . GetMethod ( nameof ( BuildPersistentTuple ) , BindingFlags . NonPublic | BindingFlags . Static ) ;
3232 private static readonly MethodInfo GetTupleSegmentMethod = typeof ( ExpressionMaterializer ) . GetMethod ( nameof ( GetTupleSegment ) , BindingFlags . NonPublic | BindingFlags . Static ) ;
3333 private static readonly MethodInfo GetParameterValueMethod = WellKnownOrmTypes . ParameterContext . GetMethod ( nameof ( ParameterContext . GetValue ) ) ;
@@ -246,12 +246,29 @@ protected override Expression VisitStructureFieldExpression(StructureFieldExpres
246246 if ( expression . Owner == null ) {
247247 var typeInfo = expression . PersistentType ;
248248 var tuplePrototype = typeInfo . TuplePrototype ;
249- var mappingInfo = expression . Fields
249+
250+ var mappingSequence = expression . Fields
250251 . OfExactlyFieldExpression ( )
251252 . OrderBy ( static f => f . Field . MappingInfo . Offset )
252253 . Select ( static f => new Pair < int > ( f . Field . MappingInfo . Offset , f . Mapping . Offset ) )
253- . Distinct ( )
254- . ToArray ( ) ;
254+ . Distinct ( ) ;
255+
256+ Pair < int > [ ] mappingInfo ;
257+ if ( expression . Fields . Count > NumberOfItemsOnStack * 2 ) {
258+ mappingInfo = mappingSequence . ToArray ( ) ;
259+ }
260+ else {
261+ Span < Pair < int > > mappingInfoSpan = ( expression . Fields . Count < NumberOfItemsOnStack )
262+ ? stackalloc Pair < int > [ expression . Fields . Count ]
263+ : new Pair < int > [ expression . Fields . Count ] ;
264+
265+ int actualCount = 0 ;
266+ foreach ( var map in mappingSequence ) {
267+ mappingInfoSpan [ actualCount ++ ] = map ;
268+ }
269+
270+ mappingInfo = mappingInfoSpan . Slice ( 0 , actualCount ) . ToArray ( ) ;
271+ }
255272
256273 var columnMap = MaterializationHelper . CreateSingleSourceMap ( tuplePrototype . Count , mappingInfo ) ;
257274
@@ -294,12 +311,29 @@ protected override Expression VisitStructureExpression(StructureExpression expre
294311
295312 var typeInfo = expression . PersistentType ;
296313 var tuplePrototype = typeInfo . TuplePrototype ;
297- var mappingInfo = expression . Fields
314+
315+ var mappingSequence = expression . Fields
298316 . OfExactlyFieldExpression ( )
299317 . OrderBy ( static f => f . Field . MappingInfo . Offset )
300318 . Select ( static f => new Pair < int > ( f . Field . MappingInfo . Offset , f . Mapping . Offset ) )
301- . Distinct ( )
302- . ToArray ( ) ;
319+ . Distinct ( ) ;
320+
321+ Pair < int > [ ] mappingInfo ;
322+ if ( expression . Fields . Count > NumberOfItemsOnStack * 2 ) {
323+ mappingInfo = mappingSequence . ToArray ( ) ;
324+ }
325+ else {
326+ Span < Pair < int > > mappingInfoSpan = ( expression . Fields . Count < NumberOfItemsOnStack )
327+ ? stackalloc Pair < int > [ expression . Fields . Count ]
328+ : new Pair < int > [ expression . Fields . Count ] ;
329+
330+ int actualCount = 0 ;
331+ foreach ( var map in mappingSequence ) {
332+ mappingInfoSpan [ actualCount ++ ] = map ;
333+ }
334+
335+ mappingInfo = mappingInfoSpan . Slice ( 0 , actualCount ) . ToArray ( ) ;
336+ }
303337
304338 var columnMap = MaterializationHelper . CreateSingleSourceMap ( tuplePrototype . Count , mappingInfo ) ;
305339
@@ -358,12 +392,28 @@ private Expression CreateEntity(IEntityExpression expression, Expression tupleEx
358392 var typeIdField = expression . Fields . SingleOrDefault ( f => f . Name == WellKnown . TypeIdFieldName ) ;
359393 var typeIdIndex = typeIdField == null ? - 1 : typeIdField . Mapping . Offset ;
360394
361- var mappingInfo = expression . Fields
395+ var mappingSequence = expression . Fields
362396 . OfExactlyFieldExpression ( )
363397 . OrderBy ( static f => f . Field . MappingInfo . Offset )
364398 . Select ( static f => new Pair < int > ( f . Field . MappingInfo . Offset , f . Mapping . Offset ) )
365- . Distinct ( )
366- . ToArray ( ) ;
399+ . Distinct ( ) ;
400+
401+ Pair < int > [ ] mappingInfo ;
402+ if ( expression . Fields . Count > NumberOfItemsOnStack * 4 ) {
403+ mappingInfo = mappingSequence . ToArray ( ) ;
404+ }
405+ else {
406+ Span < Pair < int > > mappingInfoSpan = ( expression . Fields . Count < NumberOfItemsOnStack )
407+ ? stackalloc Pair < int > [ expression . Fields . Count ]
408+ : new Pair < int > [ expression . Fields . Count ] ;
409+
410+ int actualCount = 0 ;
411+ foreach ( var map in mappingSequence ) {
412+ mappingInfoSpan [ actualCount ++ ] = map ;
413+ }
414+
415+ mappingInfo = mappingInfoSpan . Slice ( 0 , actualCount ) . ToArray ( ) ;
416+ }
367417
368418 var isMaterializedExpression = Expression . Call (
369419 itemMaterializationContextParameter ,
0 commit comments