Skip to content

Commit ca837a4

Browse files
authored
Merge pull request #331 from DataObjects-NET/master-indexinfo-imp
Improves memory efficiency of building indexes.
2 parents 4ac6895 + 3d3649f commit ca837a4

4 files changed

Lines changed: 73 additions & 41 deletions

File tree

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.ClassTable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private void BuildClassTableIndexes(TypeInfo type)
120120
var filteredIndex = BuildFilterIndex(type, ancestorIndex, filterByTypes);
121121
baseIndexes.Push(filteredIndex);
122122
}
123-
var virtualPrimaryIndex = baseIndexes.Count == 1
123+
var virtualPrimaryIndex = baseIndexes.Count == 1
124124
? baseIndexes.Pop()
125125
: BuildJoinIndex(type, baseIndexes);
126126
type.Indexes.Add(virtualPrimaryIndex);

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.ConcreteTable.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,9 @@ private void BuildConcreteTableIndexes(TypeInfo type)
9393

9494
// Build primary virtual union index
9595
if (descendants.Count > 0) {
96-
var indexesToUnion = new List<IndexInfo>(descendants.Count + 1) { type.Indexes.PrimaryIndex };
97-
foreach (var index in descendants.Select(static t => t.Indexes.PrimaryIndex)) {
98-
var indexView = BuildViewIndex(type, index);
99-
indexesToUnion.Add(indexView);
100-
}
96+
var indexesToUnion = descendants.Select(t => BuildViewIndex(type, t.Indexes.PrimaryIndex))
97+
.Prepend(type.Indexes.PrimaryIndex);
98+
10199
var virtualPrimaryIndex = BuildUnionIndex(type, indexesToUnion);
102100
type.Indexes.Add(virtualPrimaryIndex);
103101

Orm/Xtensive.Orm/Orm/Building/Builders/IndexBuilder.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,10 @@ private void BuildInterfaceIndexes()
166166
var filterIndex = BuildFilterIndex(implementor,
167167
typedIndex ?? typeIndexes.Dequeue(),
168168
NonAbstractTypeWithDescendants(implementor, hierarchyImplementors));
169-
var indexesToJoin = new List<IndexInfo>(1 + typeIndexes.Count);
170-
indexesToJoin.Add(filterIndex);
171-
indexesToJoin.AddRange(typeIndexes);
172169

173-
var indexToApplyView = indexesToJoin.Count > 1
174-
? BuildJoinIndex(implementor, indexesToJoin)
175-
: indexesToJoin[0];
170+
var indexToApplyView = typeIndexes.Count > 0
171+
? BuildJoinIndex(implementor, typeIndexes.Prepend(filterIndex))
172+
: filterIndex;
176173
var indexView = BuildViewIndex(@interface, indexToApplyView);
177174
underlyingIndex.UnderlyingIndexes.Add(indexView);
178175
}
@@ -499,7 +496,7 @@ private IndexInfo BuildTypedIndex(TypeInfo reflectedType, IndexInfo realIndex)
499496
var attributes = realIndex.Attributes
500497
& (IndexAttributes.Primary | IndexAttributes.Secondary | IndexAttributes.Unique | IndexAttributes.Abstract)
501498
| IndexAttributes.Typed | IndexAttributes.Virtual;
502-
var result = new IndexInfo(reflectedType, attributes, realIndex, Array.Empty<IndexInfo>());
499+
var result = new IndexInfo(reflectedType, attributes, realIndex, addAncestorToUnderlyings: true);
503500

504501
// Adding key columns
505502
foreach (KeyValuePair<ColumnInfo, Direction> pair in realIndex.KeyColumns) {
@@ -534,7 +531,7 @@ private IndexInfo BuildFilterIndex(TypeInfo reflectedType, IndexInfo indexToFilt
534531
var attributes = indexToFilter.Attributes
535532
& (IndexAttributes.Primary | IndexAttributes.Secondary | IndexAttributes.Unique | IndexAttributes.Abstract)
536533
| IndexAttributes.Filtered | IndexAttributes.Virtual;
537-
var result = new IndexInfo(reflectedType, attributes, indexToFilter, Array.Empty<IndexInfo>()) {
534+
var result = new IndexInfo(reflectedType, attributes, indexToFilter, addAncestorToUnderlyings: true) {
538535
FilterByTypes = filterByTypes
539536
};
540537

@@ -563,11 +560,10 @@ private IndexInfo BuildJoinIndex(TypeInfo reflectedType, IEnumerable<IndexInfo>
563560
{
564561
var nameBuilder = context.NameBuilder;
565562
var firstIndex = indexesToJoin.First();
566-
var otherIndexes = indexesToJoin.Skip(1).ToArray();
567563
var attributes = firstIndex.Attributes
568564
& (IndexAttributes.Primary | IndexAttributes.Secondary | IndexAttributes.Unique)
569565
| IndexAttributes.Join | IndexAttributes.Virtual;
570-
var result = new IndexInfo(reflectedType, attributes, firstIndex, otherIndexes);
566+
var result = new IndexInfo(reflectedType, attributes, indexesToJoin);
571567

572568
// Adding key columns
573569
foreach (KeyValuePair<ColumnInfo, Direction> pair in firstIndex.KeyColumns) {
@@ -648,11 +644,10 @@ private IndexInfo BuildUnionIndex(TypeInfo reflectedType, IEnumerable<IndexInfo>
648644
{
649645
var nameBuilder = context.NameBuilder;
650646
var firstIndex = indexesToUnion.First();
651-
var otherIndexes = indexesToUnion.Skip(1).ToArray();
652647
var attributes = firstIndex.Attributes
653648
& (IndexAttributes.Primary | IndexAttributes.Secondary | IndexAttributes.Unique)
654649
| IndexAttributes.Union | IndexAttributes.Virtual;
655-
var result = new IndexInfo(reflectedType, attributes, firstIndex, otherIndexes);
650+
var result = new IndexInfo(reflectedType, attributes, indexesToUnion);
656651

657652
// Adding key columns
658653
foreach (KeyValuePair<ColumnInfo, Direction> pair in firstIndex.KeyColumns) {
@@ -685,7 +680,7 @@ private IndexInfo BuildViewIndex(TypeInfo reflectedType, IndexInfo indexToApplyV
685680
var attributes = indexToApplyView.Attributes
686681
& (IndexAttributes.Primary | IndexAttributes.Secondary | IndexAttributes.Unique | IndexAttributes.Abstract)
687682
| IndexAttributes.View | IndexAttributes.Virtual;
688-
var result = new IndexInfo(reflectedType, attributes, indexToApplyView, Array.Empty<IndexInfo>());
683+
var result = new IndexInfo(reflectedType, attributes, indexToApplyView, addAncestorToUnderlyings: true);
689684

690685
// Adding key columns
691686
foreach (KeyValuePair<ColumnInfo, Direction> pair in indexToApplyView.KeyColumns) {

Orm/Xtensive.Orm/Orm/Model/IndexInfo.cs

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -286,32 +286,38 @@ public override void UpdateState()
286286
base.UpdateState();
287287
CreateColumns();
288288
ValueColumns.UpdateState();
289-
foreach (IndexInfo baseIndex in UnderlyingIndexes) {
289+
foreach (var baseIndex in UnderlyingIndexes) {
290290
baseIndex.UpdateState();
291291
}
292292
filter?.UpdateState();
293293
CreateTupleDescriptors();
294294

295-
if (!IsPrimary)
295+
if (!IsPrimary) {
296296
return;
297+
}
297298

298-
var system = new List<int>();
299+
var keyColumnsCount = KeyColumns.Count;
300+
var system = new List<int>(keyColumnsCount + 1);
299301
var lazy = new List<int>();
300-
var regular = new List<int>();
302+
var regular = new List<int>(Columns.Count - keyColumnsCount);
301303

302304
for (int i = 0, count = Columns.Count; i < count; i++) {
303305
var item = Columns[i];
304-
if (item.IsPrimaryKey || item.IsSystem)
306+
if (item.IsPrimaryKey || item.IsSystem) {
305307
system.Add(i);
308+
}
309+
else if (item.IsLazyLoad) {
310+
lazy.Add(i);
311+
}
306312
else {
307-
if (item.IsLazyLoad)
308-
lazy.Add(i);
309-
else
310-
regular.Add(i);
313+
regular.Add(i);
311314
}
312315
}
313316

314-
ColumnIndexMap = new ColumnIndexMap(system, regular, lazy);
317+
ColumnIndexMap = new ColumnIndexMap(
318+
system,
319+
(regular.Count == 0) ? Array.Empty<int>() : regular,
320+
(lazy.Count == 0) ? Array.Empty<int>() : lazy);
315321
}
316322

317323
/// <inheritdoc/>
@@ -345,15 +351,15 @@ private void CreateColumns()
345351
Columns = Array.AsReadOnly(KeyColumns.Select(static pair => pair.Key).Concat(ValueColumns).ToArray(KeyColumns.Count + ValueColumns.Count));
346352
}
347353

348-
// Constructors
349-
350-
private IndexInfo()
354+
/// Unsubscribe ColumnInfoCollections from FieldInfo events to avoid memory leak.
355+
public void Dispose()
351356
{
352-
KeyColumns = new DirectionCollection<ColumnInfo>();
353-
IncludedColumns = new ColumnInfoCollection(this, "IncludedColumns");
354-
ValueColumns = new ColumnInfoCollection(this, "ValueColumns");
357+
IncludedColumns.Clear();
358+
ValueColumns.Clear();
355359
}
356360

361+
// Constructors
362+
357363
/// <summary>
358364
/// Initializes a new instance of this class.
359365
/// </summary>
@@ -372,9 +378,10 @@ public IndexInfo(TypeInfo declaringType, IndexAttributes indexAttributes)
372378
/// Initializes a new instance of this class.
373379
/// </summary>
374380
/// <param name="reflectedType">Reflected type.</param>
375-
/// <param name="ancestorIndex">The ancestors index.</param>
376381
/// <param name="indexAttributes"><see cref="IndexAttributes"/> attributes for this instance.</param>
377-
public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexInfo ancestorIndex)
382+
/// <param name="ancestorIndex">The ancestors index.</param>
383+
/// <param name="addAncestorToUnderlyings"><see langword="true"/> if <paramref name="ancestorIndex"/> should also be treated as underlying index.</param>
384+
public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexInfo ancestorIndex, bool addAncestorToUnderlyings = false)
378385
: this()
379386
{
380387
DeclaringType = ancestorIndex.DeclaringType;
@@ -385,6 +392,10 @@ public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexI
385392
filterExpression = ancestorIndex.FilterExpression;
386393
DeclaringIndex = ancestorIndex.DeclaringIndex;
387394
shortName = ancestorIndex.ShortName;
395+
396+
if (addAncestorToUnderlyings) {
397+
UnderlyingIndexes.Add(ancestorIndex);
398+
}
388399
}
389400

390401
/// <summary>
@@ -394,6 +405,7 @@ public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexI
394405
/// <param name="indexAttributes">The index attributes.</param>
395406
/// <param name="baseIndex">Base index.</param>
396407
/// <param name="baseIndexes">The base indexes.</param>
408+
[Obsolete("Use either IndexInfo(reflectedType, indexAttributes, ancestorIndex, true) in case of one base index or varaint with sequence of indexes")]
397409
public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexInfo baseIndex, params IndexInfo[] baseIndexes)
398410
: this()
399411
{
@@ -412,6 +424,33 @@ public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IndexI
412424
UnderlyingIndexes.Add(info);
413425
}
414426

427+
/// <summary>
428+
/// Initializes a new instance of this class.
429+
/// </summary>
430+
/// <param name="reflectedType">Reflected type.</param>
431+
/// <param name="indexAttributes">The index attributes.</param>
432+
/// <param name="baseIndexes">The base indexes, first of which will be used as source index properties.</param>
433+
public IndexInfo(TypeInfo reflectedType, IndexAttributes indexAttributes, IEnumerable<IndexInfo> baseIndexes)
434+
: this()
435+
{
436+
this.ReflectedType = reflectedType;
437+
attributes = indexAttributes;
438+
439+
foreach (var info in baseIndexes) {
440+
if (DeclaringType is null) {
441+
DeclaringType = info.DeclaringType;
442+
fillFactor = info.FillFactor;
443+
filterExpression = info.FilterExpression;
444+
DeclaringIndex = info.DeclaringIndex;
445+
shortName = info.ShortName;
446+
}
447+
UnderlyingIndexes.Add(info);
448+
}
449+
if (UnderlyingIndexes.Count == 0) {
450+
throw new ArgumentException(Strings.ExSequenceContainsNoElements, nameof(baseIndexes));
451+
}
452+
}
453+
415454
/// <summary>
416455
/// Used for cloning only.
417456
/// </summary>
@@ -430,11 +469,11 @@ private IndexInfo(IndexInfo original)
430469
DeclaringIndex = original.DeclaringIndex.DeclaringIndex;
431470
}
432471

433-
/// Unsubscribe ColumnInfoCollections from FieldInfo events to avoid memory leak.
434-
public void Dispose()
472+
private IndexInfo()
435473
{
436-
IncludedColumns.Clear();
437-
ValueColumns.Clear();
474+
KeyColumns = new DirectionCollection<ColumnInfo>();
475+
IncludedColumns = new ColumnInfoCollection(this, "IncludedColumns");
476+
ValueColumns = new ColumnInfoCollection(this, "ValueColumns");
438477
}
439478
}
440479
}

0 commit comments

Comments
 (0)