Skip to content

Commit ba31a6a

Browse files
authored
PERF-269: Optimization: DerivedColumn class so decrease allocation size of MappedColumn (#382)
* Optimization: `DerivedColumn` class so decrease allocation size of `MappedColumn` * Simplify * Refactor * Improve .ToString() * Add comment
1 parent 8c9b837 commit ba31a6a

File tree

5 files changed

+122
-179
lines changed

5 files changed

+122
-179
lines changed

Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace Xtensive.Orm.Rse
1212
/// Aggregate column of the <see cref="RecordSetHeader"/>.
1313
/// </summary>
1414
[Serializable]
15-
public sealed class AggregateColumn : Column
15+
public sealed class AggregateColumn : DerivedColumn
1616
{
1717
private const string ToStringFormat = "{0} = {1} on ({2})";
1818

@@ -70,19 +70,19 @@ public AggregateColumn(AggregateColumnDescriptor descriptor, ColNum index, Type
7070
#region Clone constructors
7171

7272
private AggregateColumn(AggregateColumn column, string newName)
73-
: base(newName, column.Index, column.Type, column)
73+
: base(newName, column.Index, column.Type, column.Origin)
7474
{
7575
AggregateType = column.AggregateType;
7676
SourceIndex = column.SourceIndex;
7777
}
7878

7979
private AggregateColumn(AggregateColumn column, ColNum newIndex)
80-
: base(column.Name, newIndex, column.Type, column)
80+
: base(column.Name, newIndex, column.Type, column.Origin)
8181
{
8282
AggregateType = column.AggregateType;
8383
SourceIndex = column.SourceIndex;
8484
}
8585

8686
#endregion
8787
}
88-
}
88+
}

Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Xtensive.Orm.Rse
1818
/// Calculated column of the <see cref="RecordSetHeader"/>.
1919
/// </summary>
2020
[Serializable]
21-
public sealed class CalculatedColumn : Column
21+
public sealed class CalculatedColumn : DerivedColumn
2222
{
2323
private const string ToStringFormat = "{0} = {1}";
2424

@@ -63,17 +63,17 @@ public CalculatedColumn(CalculatedColumnDescriptor descriptor, ColNum index)
6363
#region Clone constructors
6464

6565
private CalculatedColumn(CalculatedColumn column, string newName)
66-
: base(newName, column.Index, column.Type, column)
66+
: base(newName, column.Index, column.Type, column.Origin)
6767
{
6868
Expression = column.Expression;
6969
}
7070

7171
private CalculatedColumn(CalculatedColumn column, ColNum newIndex)
72-
: base(column.Name, newIndex, column.Type, column)
72+
: base(column.Name, newIndex, column.Type, column.Origin)
7373
{
7474
Expression = column.Expression;
7575
}
7676

7777
#endregion
7878
}
79-
}
79+
}

Orm/Xtensive.Orm/Orm/Rse/Column.cs

Lines changed: 64 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,109 +4,84 @@
44
// Created by: Elena Vakhtina
55
// Created: 2008.09.09
66

7-
using System;
7+
namespace Xtensive.Orm.Rse;
88

9-
10-
namespace Xtensive.Orm.Rse
9+
/// <summary>
10+
/// Base class for any column of the <see cref="RecordSetHeader"/>.
11+
/// </summary>
12+
[Serializable]
13+
public abstract class Column(string name, ColNum index, Type type) : IEquatable<Column>
1114
{
1215
/// <summary>
13-
/// Base class for any column of the <see cref="RecordSetHeader"/>.
16+
/// Gets origin <see cref="Column"/> for this instance.
1417
/// </summary>
15-
[Serializable]
16-
public abstract class Column : IEquatable<Column>
17-
{
18-
private const string ToStringFormat = "{0} {1} ({2})";
19-
20-
/// <summary>
21-
/// Gets origin <see cref="Column"/> for this instance.
22-
/// </summary>
23-
public Column Origin { get; private set; }
24-
25-
/// <summary>
26-
/// Gets the column name.
27-
/// </summary>
28-
public string Name { get; private set; }
29-
30-
/// <summary>
31-
/// Gets the column index.
32-
/// </summary>
33-
public ColNum Index { get; }
34-
35-
/// <summary>
36-
/// Gets the column type.
37-
/// </summary>
38-
public Type Type { get; private set; }
39-
40-
#region Equals, GetHashCode, ==, !=
18+
public virtual Column Origin => this;
4119

42-
/// <inheritdoc/>
43-
public bool Equals(Column other) =>
44-
other is not null && (ReferenceEquals(this, other) || Name == other.Name);
20+
/// <summary>
21+
/// Gets the column name.
22+
/// </summary>
23+
public string Name { get; } = name;
4524

46-
/// <inheritdoc/>
47-
public override bool Equals(object obj) => obj is Column other && Equals(other);
25+
/// <summary>
26+
/// Gets the column index.
27+
/// </summary>
28+
public ColNum Index { get; } = index;
4829

49-
/// <inheritdoc/>
50-
public override int GetHashCode() => Name.GetHashCode();
30+
/// <summary>
31+
/// Gets the column type.
32+
/// </summary>
33+
public Type Type { get; } = type;
5134

52-
/// <summary>
53-
/// Implements the operator ==.
54-
/// </summary>
55-
/// <param name="left">The left.</param>
56-
/// <param name="right">The right.</param>
57-
/// <returns>
58-
/// The result of the operator.
59-
/// </returns>
60-
public static bool operator ==(Column left, Column right) => left?.Equals(right) ?? right is null;
35+
/// <inheritdoc/>
36+
public bool Equals(Column other) =>
37+
other is not null && (ReferenceEquals(this, other) || Name == other.Name);
6138

62-
/// <summary>
63-
/// Implements the operator !=.
64-
/// </summary>
65-
/// <param name="left">The left.</param>
66-
/// <param name="right">The right.</param>
67-
/// <returns>
68-
/// The result of the operator.
69-
/// </returns>
70-
public static bool operator !=(Column left, Column right) => !(left == right);
39+
/// <inheritdoc/>
40+
public override bool Equals(object obj) => obj is Column other && Equals(other);
7141

72-
#endregion
42+
/// <inheritdoc/>
43+
public override int GetHashCode() => Name.GetHashCode();
7344

74-
/// <inheritdoc/>
75-
public override string ToString()
76-
{
77-
return string.Format(ToStringFormat, Type.Name, Name, Index);
78-
}
45+
/// <summary>
46+
/// Implements the operator ==.
47+
/// </summary>
48+
/// <param name="left">The left.</param>
49+
/// <param name="right">The right.</param>
50+
/// <returns>
51+
/// The result of the operator.
52+
/// </returns>
53+
public static bool operator ==(Column left, Column right) => left?.Equals(right) ?? right is null;
7954

80-
/// <summary>
81-
/// Creates clone of the column, but with another <see cref="Index"/>.
82-
/// </summary>
83-
/// <param name="newIndex">The new index value.</param>
84-
/// <returns>Clone of the column, but with another <see cref="Index"/>.</returns>
85-
public abstract Column Clone(ColNum newIndex);
55+
/// <summary>
56+
/// Implements the operator !=.
57+
/// </summary>
58+
/// <param name="left">The left.</param>
59+
/// <param name="right">The right.</param>
60+
/// <returns>
61+
/// The result of the operator.
62+
/// </returns>
63+
public static bool operator !=(Column left, Column right) => !(left == right);
8664

87-
/// <summary>
88-
/// Creates clone of the column, but with another <see cref="Name"/>.
89-
/// </summary>
90-
/// <param name="newName">The new name value.</param>
91-
/// <returns>Clone of the column, but with another <see cref="Name"/>.</returns>
92-
public abstract Column Clone(string newName);
65+
/// <inheritdoc/>
66+
public override string ToString() => $"{Type.Name} {Name} ({Index})";
9367

68+
/// <summary>
69+
/// Creates clone of the column, but with another <see cref="Index"/>.
70+
/// </summary>
71+
/// <param name="newIndex">The new index value.</param>
72+
/// <returns>Clone of the column, but with another <see cref="Index"/>.</returns>
73+
public abstract Column Clone(ColNum newIndex);
9474

95-
// Constructors
75+
/// <summary>
76+
/// Creates clone of the column, but with another <see cref="Name"/>.
77+
/// </summary>
78+
/// <param name="newName">The new name value.</param>
79+
/// <returns>Clone of the column, but with another <see cref="Name"/>.</returns>
80+
public abstract Column Clone(string newName);
81+
}
9682

97-
/// <summary>
98-
/// Initializes a new instance of this class..
99-
/// </summary>
100-
/// <param name="name"><see cref="Name"/> property value.</param>
101-
/// <param name="index"><see cref="Index"/> property value.</param>
102-
/// <param name="type"><see cref="Type"/> property value.</param>
103-
/// <param name="originalColumn">Original column.</param>
104-
protected Column(string name, ColNum index, Type type, Column originalColumn)
105-
{
106-
Name = name;
107-
Index = index;
108-
Type = type;
109-
Origin = originalColumn is null ? this : originalColumn.Origin;
110-
}
111-
}
83+
public abstract class DerivedColumn(string name, ColNum index, Type type, Column origin)
84+
: Column(name, index, type)
85+
{
86+
public override Column Origin => origin ?? this;
11287
}

Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs

Lines changed: 46 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -4,97 +4,65 @@
44
// Created by: Alexey Kochetov
55
// Created: 2007.09.21
66

7-
using System;
87
using Xtensive.Orm.Model;
98

10-
namespace Xtensive.Orm.Rse
9+
namespace Xtensive.Orm.Rse;
10+
11+
/// <summary>
12+
/// Mapped column of the <see cref="RecordSetHeader"/>.
13+
/// </summary>
14+
[Serializable]
15+
public class MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type)
16+
: Column(name, index, type)
1117
{
1218
/// <summary>
13-
/// Mapped column of the <see cref="RecordSetHeader"/>.
19+
/// Gets the reference that describes a column.
1420
/// </summary>
15-
[Serializable]
16-
public sealed class MappedColumn : Column
17-
{
18-
private const string ToStringFormat = "{0} = {1}";
19-
20-
/// <summary>
21-
/// Gets the reference that describes a column.
22-
/// </summary>
23-
public ColumnInfoRef ColumnInfoRef { get; }
24-
25-
/// <inheritdoc/>
26-
public override string ToString()
27-
{
28-
return string.Format(ToStringFormat, base.ToString(), ColumnInfoRef);
29-
}
30-
31-
/// <inheritdoc/>
32-
public override Column Clone(ColNum newIndex)
33-
{
34-
return new MappedColumn(ColumnInfoRef, Name, newIndex, Type);
35-
}
21+
public ColumnInfoRef ColumnInfoRef { get; } = columnInfoRef;
3622

37-
/// <inheritdoc/>
38-
public override Column Clone(string newName)
39-
{
40-
return new MappedColumn(this, newName);
41-
}
23+
/// <inheritdoc/>
24+
public override string ToString() => $"{base.ToString()} = {ColumnInfoRef}";
4225

43-
// Constructors
26+
/// <inheritdoc/>
27+
public override Column Clone(ColNum newIndex) => new MappedColumn(ColumnInfoRef, Name, newIndex, Type);
4428

45-
#region Basic constructors
29+
/// <inheritdoc/>
30+
public override Column Clone(string newName) => new DerivedMappedColumn(newName, Index, Type, Origin, ColumnInfoRef);
4631

47-
/// <summary>
48-
/// Initializes a new instance of this class.
49-
/// </summary>
50-
/// <param name="name"><see cref="Column.Name"/> property value.</param>
51-
/// <param name="index"><see cref="Column.Index"/> property value.</param>
52-
/// <param name="type"><see cref="Column.Type"/> property value.</param>
53-
public MappedColumn(string name, ColNum index, Type type)
54-
: this(default, name, index, type)
55-
{
56-
}
32+
// Constructors
5733

58-
/// <summary>
59-
/// Initializes a new instance of this class.
60-
/// </summary>
61-
/// <param name="columnInfoRef"><see cref="ColumnInfoRef"/> property value.</param>
62-
/// <param name="index"><see cref="Column.Index"/> property value.</param>
63-
/// <param name="type"><see cref="Column.Type"/> property value.</param>
64-
public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type)
65-
: this(columnInfoRef, columnInfoRef.ColumnName, index, type)
66-
{
67-
}
34+
#region Basic constructors
6835

69-
/// <summary>
70-
/// Initializes a new instance of this class.
71-
/// </summary>
72-
/// <param name="columnInfoRef"><see cref="ColumnInfoRef"/> property value.</param>
73-
/// <param name="name"><see cref="Column.Name"/> property value.</param>
74-
/// <param name="index"><see cref="Column.Index"/> property value.</param>
75-
/// <param name="type"><see cref="Column.Type"/> property value.</param>
76-
public MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type)
77-
: base(name, index, type, null)
78-
{
79-
ColumnInfoRef = columnInfoRef;
80-
}
81-
82-
#endregion
36+
/// <summary>
37+
/// Initializes a new instance of this class.
38+
/// </summary>
39+
/// <param name="name"><see cref="Column.Name"/> property value.</param>
40+
/// <param name="index"><see cref="Column.Index"/> property value.</param>
41+
/// <param name="type"><see cref="Column.Type"/> property value.</param>
42+
public MappedColumn(string name, ColNum index, Type type)
43+
: this(default, name, index, type)
44+
{
45+
}
8346

84-
#region Clone constructors
47+
/// <summary>
48+
/// Initializes a new instance of this class.
49+
/// </summary>
50+
/// <param name="columnInfoRef"><see cref="ColumnInfoRef"/> property value.</param>
51+
/// <param name="index"><see cref="Column.Index"/> property value.</param>
52+
/// <param name="type"><see cref="Column.Type"/> property value.</param>
53+
public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type)
54+
: this(columnInfoRef, columnInfoRef.ColumnName, index, type)
55+
{
56+
}
8557

86-
private MappedColumn(MappedColumn column, string newName)
87-
: base(newName, column.Index, column.Type, column)
88-
{
89-
ColumnInfoRef = column.ColumnInfoRef;
90-
}
58+
#endregion
9159

92-
private MappedColumn(MappedColumn column, ColNum newIndex)
93-
: base(column.Name, newIndex, column.Type, column)
94-
{
95-
ColumnInfoRef = column.ColumnInfoRef;
96-
}
60+
}
9761

98-
#endregion
99-
}
62+
// The purpose of this class is minimize allocation size of `MappedColumn`
63+
// Non self-referencing `Origin` property is a rare case
64+
internal sealed class DerivedMappedColumn(string name, ColNum index, Type type, Column origin, ColumnInfoRef columnInfoRef)
65+
: MappedColumn(columnInfoRef, name, index, type)
66+
{
67+
public override Column Origin => origin ?? this;
10068
}

0 commit comments

Comments
 (0)