From 9735d1160aac659df1780ed665f48529f4d2d98f Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Sun, 18 May 2025 15:29:45 -0700 Subject: [PATCH 1/5] Optimization: `DerivedColumn` class so decrease allocation size of `MappedColumn` --- Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs | 8 +- Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs | 8 +- Orm/Xtensive.Orm/Orm/Rse/Column.cs | 14 +- Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs | 147 ++++++++----------- Orm/Xtensive.Orm/Orm/Rse/SystemColumn.cs | 8 +- 5 files changed, 81 insertions(+), 104 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs index a00dfec82f..1c937a61e8 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/AggregateColumn.cs @@ -12,7 +12,7 @@ namespace Xtensive.Orm.Rse /// Aggregate column of the . /// [Serializable] - public sealed class AggregateColumn : Column + public sealed class AggregateColumn : DerivedColumn { private const string ToStringFormat = "{0} = {1} on ({2})"; @@ -70,14 +70,14 @@ public AggregateColumn(AggregateColumnDescriptor descriptor, ColNum index, Type #region Clone constructors private AggregateColumn(AggregateColumn column, string newName) - : base(newName, column.Index, column.Type, column) + : base(newName, column.Index, column.Type, column.Origin) { AggregateType = column.AggregateType; SourceIndex = column.SourceIndex; } private AggregateColumn(AggregateColumn column, ColNum newIndex) - : base(column.Name, newIndex, column.Type, column) + : base(column.Name, newIndex, column.Type, column.Origin) { AggregateType = column.AggregateType; SourceIndex = column.SourceIndex; @@ -85,4 +85,4 @@ private AggregateColumn(AggregateColumn column, ColNum newIndex) #endregion } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs index abbea1ce3f..1abb8d19d7 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/CalculatedColumn.cs @@ -18,7 +18,7 @@ namespace Xtensive.Orm.Rse /// Calculated column of the . /// [Serializable] - public sealed class CalculatedColumn : Column + public sealed class CalculatedColumn : DerivedColumn { private const string ToStringFormat = "{0} = {1}"; @@ -63,17 +63,17 @@ public CalculatedColumn(CalculatedColumnDescriptor descriptor, ColNum index) #region Clone constructors private CalculatedColumn(CalculatedColumn column, string newName) - : base(newName, column.Index, column.Type, column) + : base(newName, column.Index, column.Type, column.Origin) { Expression = column.Expression; } private CalculatedColumn(CalculatedColumn column, ColNum newIndex) - : base(column.Name, newIndex, column.Type, column) + : base(column.Name, newIndex, column.Type, column.Origin) { Expression = column.Expression; } #endregion } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Orm/Rse/Column.cs b/Orm/Xtensive.Orm/Orm/Rse/Column.cs index 8784ab23b5..0de367dba8 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Column.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Column.cs @@ -4,9 +4,6 @@ // Created by: Elena Vakhtina // Created: 2008.09.09 -using System; - - namespace Xtensive.Orm.Rse { /// @@ -20,7 +17,7 @@ public abstract class Column : IEquatable /// /// Gets origin for this instance. /// - public Column Origin { get; private set; } + public virtual Column Origin => this; /// /// Gets the column name. @@ -101,12 +98,17 @@ public override string ToString() /// property value. /// property value. /// Original column. - protected Column(string name, ColNum index, Type type, Column originalColumn) + protected Column(string name, ColNum index, Type type) { Name = name; Index = index; Type = type; - Origin = originalColumn is null ? this : originalColumn.Origin; } } + + public abstract class DerivedColumn(string name, ColNum index, Type type, Column origin) + : Column(name, index, type) + { + public override Column Origin => origin ?? this; + } } diff --git a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs index 1570255997..e430fdc8e7 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs @@ -4,97 +4,72 @@ // Created by: Alexey Kochetov // Created: 2007.09.21 -using System; using Xtensive.Orm.Model; -namespace Xtensive.Orm.Rse +namespace Xtensive.Orm.Rse; + +/// +/// Mapped column of the . +/// +[Serializable] +public sealed class MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type) + : Column(name, index, type) { + private const string ToStringFormat = "{0} = {1}"; + + /// + /// Gets the reference that describes a column. + /// + public ColumnInfoRef ColumnInfoRef { get; } = columnInfoRef; + + /// + public override string ToString() + { + return string.Format(ToStringFormat, base.ToString(), ColumnInfoRef); + } + + /// + public override Column Clone(ColNum newIndex) => new MappedColumn(ColumnInfoRef, Name, newIndex, Type); + + /// + public override Column Clone(string newName) => new DerivedMappedColumn(newName, Index, Type, Origin, ColumnInfoRef); + + // Constructors + + #region Basic constructors + /// - /// Mapped column of the . + /// Initializes a new instance of this class. /// - [Serializable] - public sealed class MappedColumn : Column + /// property value. + /// property value. + /// property value. + public MappedColumn(string name, ColNum index, Type type) + : this(default, name, index, type) { - private const string ToStringFormat = "{0} = {1}"; - - /// - /// Gets the reference that describes a column. - /// - public ColumnInfoRef ColumnInfoRef { get; } - - /// - public override string ToString() - { - return string.Format(ToStringFormat, base.ToString(), ColumnInfoRef); - } - - /// - public override Column Clone(ColNum newIndex) - { - return new MappedColumn(ColumnInfoRef, Name, newIndex, Type); - } - - /// - public override Column Clone(string newName) - { - return new MappedColumn(this, newName); - } - - // Constructors - - #region Basic constructors - - /// - /// Initializes a new instance of this class. - /// - /// property value. - /// property value. - /// property value. - public MappedColumn(string name, ColNum index, Type type) - : this(default, name, index, type) - { - } - - /// - /// Initializes a new instance of this class. - /// - /// property value. - /// property value. - /// property value. - public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type) - : this(columnInfoRef, columnInfoRef.ColumnName, index, type) - { - } - - /// - /// Initializes a new instance of this class. - /// - /// property value. - /// property value. - /// property value. - /// property value. - public MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type) - : base(name, index, type, null) - { - ColumnInfoRef = columnInfoRef; - } - - #endregion - - #region Clone constructors - - private MappedColumn(MappedColumn column, string newName) - : base(newName, column.Index, column.Type, column) - { - ColumnInfoRef = column.ColumnInfoRef; - } - - private MappedColumn(MappedColumn column, ColNum newIndex) - : base(column.Name, newIndex, column.Type, column) - { - ColumnInfoRef = column.ColumnInfoRef; - } - - #endregion } + + /// + /// Initializes a new instance of this class. + /// + /// property value. + /// property value. + /// property value. + public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type) + : this(columnInfoRef, columnInfoRef.ColumnName, index, type) + { + } + + #endregion + +} + +internal sealed class DerivedMappedColumn(string name, ColNum index, Type type, Column origin, ColumnInfoRef columnInfoRef) + : DerivedColumn(name, index, type, origin) +{ + public ColumnInfoRef ColumnInfoRef { get; } = columnInfoRef; + + public override Column Clone(ColNum newIndex) => new MappedColumn(ColumnInfoRef, Name, newIndex, Type); + + public override Column Clone(string newName) => new DerivedMappedColumn(newName, Index, Type, Origin, ColumnInfoRef); } diff --git a/Orm/Xtensive.Orm/Orm/Rse/SystemColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/SystemColumn.cs index fff2504432..f7d8bffdec 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/SystemColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/SystemColumn.cs @@ -13,7 +13,7 @@ namespace Xtensive.Orm.Rse /// System column of the . /// [Serializable] - public class SystemColumn : Column + public class SystemColumn : DerivedColumn { /// public override Column Clone(ColNum newIndex) @@ -41,15 +41,15 @@ public SystemColumn(string name, ColNum index, Type type) #region Clone constructors private SystemColumn(SystemColumn column, ColNum newIndex) - : base(column.Name, newIndex, column.Type, column) + : base(column.Name, newIndex, column.Type, column.Origin) { } private SystemColumn(SystemColumn column, string newName) - : base(newName, column.Index, column.Type, column) + : base(newName, column.Index, column.Type, column.Origin) { } #endregion } -} \ No newline at end of file +} From 4be4919d5b8bf52bd815ffcce662252670aa33ee Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Sun, 18 May 2025 18:06:39 -0700 Subject: [PATCH 2/5] Simplify --- Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs index e430fdc8e7..a5650a3684 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs @@ -12,7 +12,7 @@ namespace Xtensive.Orm.Rse; /// Mapped column of the . /// [Serializable] -public sealed class MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type) +public class MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type) : Column(name, index, type) { private const string ToStringFormat = "{0} = {1}"; @@ -65,11 +65,7 @@ public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type) } internal sealed class DerivedMappedColumn(string name, ColNum index, Type type, Column origin, ColumnInfoRef columnInfoRef) - : DerivedColumn(name, index, type, origin) + : MappedColumn(columnInfoRef, name, index, type) { - public ColumnInfoRef ColumnInfoRef { get; } = columnInfoRef; - - public override Column Clone(ColNum newIndex) => new MappedColumn(ColumnInfoRef, Name, newIndex, Type); - - public override Column Clone(string newName) => new DerivedMappedColumn(newName, Index, Type, Origin, ColumnInfoRef); + public override Column Origin => origin ?? this; } From 9ff85a249f7c2c899ac1ade163e8639e3c458aa2 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Sun, 18 May 2025 18:21:43 -0700 Subject: [PATCH 3/5] Refactor --- Orm/Xtensive.Orm/Orm/Rse/Column.cs | 157 ++++++++++++----------------- 1 file changed, 65 insertions(+), 92 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/Column.cs b/Orm/Xtensive.Orm/Orm/Rse/Column.cs index 0de367dba8..623f42913a 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/Column.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/Column.cs @@ -4,111 +4,84 @@ // Created by: Elena Vakhtina // Created: 2008.09.09 -namespace Xtensive.Orm.Rse +namespace Xtensive.Orm.Rse; + +/// +/// Base class for any column of the . +/// +[Serializable] +public abstract class Column(string name, ColNum index, Type type) : IEquatable { /// - /// Base class for any column of the . + /// Gets origin for this instance. /// - [Serializable] - public abstract class Column : IEquatable - { - private const string ToStringFormat = "{0} {1} ({2})"; - - /// - /// Gets origin for this instance. - /// - public virtual Column Origin => this; - - /// - /// Gets the column name. - /// - public string Name { get; private set; } - - /// - /// Gets the column index. - /// - public ColNum Index { get; } - - /// - /// Gets the column type. - /// - public Type Type { get; private set; } - - #region Equals, GetHashCode, ==, != + public virtual Column Origin => this; - /// - public bool Equals(Column other) => - other is not null && (ReferenceEquals(this, other) || Name == other.Name); - - /// - public override bool Equals(object obj) => obj is Column other && Equals(other); + /// + /// Gets the column name. + /// + public string Name { get; } = name; - /// - public override int GetHashCode() => Name.GetHashCode(); + /// + /// Gets the column index. + /// + public ColNum Index { get; } = index; - /// - /// Implements the operator ==. - /// - /// The left. - /// The right. - /// - /// The result of the operator. - /// - public static bool operator ==(Column left, Column right) => left?.Equals(right) ?? right is null; + /// + /// Gets the column type. + /// + public Type Type { get; } = type; - /// - /// Implements the operator !=. - /// - /// The left. - /// The right. - /// - /// The result of the operator. - /// - public static bool operator !=(Column left, Column right) => !(left == right); + /// + public bool Equals(Column other) => + other is not null && (ReferenceEquals(this, other) || Name == other.Name); - #endregion + /// + public override bool Equals(object obj) => obj is Column other && Equals(other); - /// - public override string ToString() - { - return string.Format(ToStringFormat, Type.Name, Name, Index); - } + /// + public override int GetHashCode() => Name.GetHashCode(); - /// - /// Creates clone of the column, but with another . - /// - /// The new index value. - /// Clone of the column, but with another . - public abstract Column Clone(ColNum newIndex); + /// + /// Implements the operator ==. + /// + /// The left. + /// The right. + /// + /// The result of the operator. + /// + public static bool operator ==(Column left, Column right) => left?.Equals(right) ?? right is null; - /// - /// Creates clone of the column, but with another . - /// - /// The new name value. - /// Clone of the column, but with another . - public abstract Column Clone(string newName); + /// + /// Implements the operator !=. + /// + /// The left. + /// The right. + /// + /// The result of the operator. + /// + public static bool operator !=(Column left, Column right) => !(left == right); + /// + public override string ToString() => $"{Type.Name} {Name} ({Index})"; - // Constructors + /// + /// Creates clone of the column, but with another . + /// + /// The new index value. + /// Clone of the column, but with another . + public abstract Column Clone(ColNum newIndex); - /// - /// Initializes a new instance of this class.. - /// - /// property value. - /// property value. - /// property value. - /// Original column. - protected Column(string name, ColNum index, Type type) - { - Name = name; - Index = index; - Type = type; - } - } + /// + /// Creates clone of the column, but with another . + /// + /// The new name value. + /// Clone of the column, but with another . + public abstract Column Clone(string newName); +} - public abstract class DerivedColumn(string name, ColNum index, Type type, Column origin) - : Column(name, index, type) - { - public override Column Origin => origin ?? this; - } +public abstract class DerivedColumn(string name, ColNum index, Type type, Column origin) + : Column(name, index, type) +{ + public override Column Origin => origin ?? this; } From 9d8ce0e1d8a4d9f3b4b97706f10e3597b8e4d12f Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Mon, 19 May 2025 11:20:14 -0700 Subject: [PATCH 4/5] Improve .ToString() --- Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs index a5650a3684..445d95397f 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs @@ -15,18 +15,13 @@ namespace Xtensive.Orm.Rse; public class MappedColumn(ColumnInfoRef columnInfoRef, string name, ColNum index, Type type) : Column(name, index, type) { - private const string ToStringFormat = "{0} = {1}"; - /// /// Gets the reference that describes a column. /// public ColumnInfoRef ColumnInfoRef { get; } = columnInfoRef; /// - public override string ToString() - { - return string.Format(ToStringFormat, base.ToString(), ColumnInfoRef); - } + public override string ToString() => $"{base.ToString()} = {ColumnInfoRef}"; /// public override Column Clone(ColNum newIndex) => new MappedColumn(ColumnInfoRef, Name, newIndex, Type); From 16c6bc5092ce9790af1a31b0e0d3b44225941017 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Mon, 19 May 2025 18:00:10 -0700 Subject: [PATCH 5/5] Add comment --- Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs index 445d95397f..5d903cba33 100644 --- a/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs +++ b/Orm/Xtensive.Orm/Orm/Rse/MappedColumn.cs @@ -59,6 +59,8 @@ public MappedColumn(ColumnInfoRef columnInfoRef, ColNum index, Type type) } +// The purpose of this class is minimize allocation size of `MappedColumn` +// Non self-referencing `Origin` property is a rare case internal sealed class DerivedMappedColumn(string name, ColNum index, Type type, Column origin, ColumnInfoRef columnInfoRef) : MappedColumn(columnInfoRef, name, index, type) {