From ba0fa22575ea438c2ced2b372525e274c407df54 Mon Sep 17 00:00:00 2001 From: Evgeny Akhtimirov Date: Mon, 6 Feb 2023 11:59:33 +0300 Subject: [PATCH 1/3] added cached boxed boolean values to BooleanType it is faster and avoids memory allocations --- .../TypesTest/BooleanTypeFixture.cs | 68 +++++++++++++++++- .../TypesTest/CharBooleanTypeFixture.cs | 71 +++++++++++++++++++ src/NHibernate/Type/BooleanType.cs | 26 ++++--- src/NHibernate/Type/CharBooleanType.cs | 7 +- 4 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 src/NHibernate.Test/TypesTest/CharBooleanTypeFixture.cs diff --git a/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs b/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs index c9c217a81e4..feaacf8c48b 100644 --- a/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs +++ b/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs @@ -1,5 +1,7 @@ -using System; +using System.Data.Common; +using NHibernate.Engine; using NHibernate.Type; +using NSubstitute; using NUnit.Framework; namespace NHibernate.Test.TypesTest @@ -22,7 +24,7 @@ protected override string TypeName [Test] public void Equals() { - BooleanType type = (BooleanType) NHibernateUtil.Boolean; + BooleanType type = NHibernateUtil.Boolean; Assert.IsTrue(type.IsEqual(true, true)); Assert.IsTrue(type.IsEqual(false, false)); @@ -50,5 +52,65 @@ public void ReadWrite() s.Flush(); s.Close(); } + + [Theory] + public void GetByIndex(bool expected) + { + const int index0 = 0; + const int index1 = 1; + BooleanType type = NHibernateUtil.Boolean; + var session = Substitute.For(); + var reader = Substitute.For(); + reader[index0].Returns(expected); + reader[index1].Returns(expected); + + var result0 = type.Get(reader, index0, session); + var result1 = type.Get(reader, index1, session); + + Assert.AreEqual(expected, (bool) result0); + Assert.AreSame(result0, result1); + } + + [Theory] + public void GetByName(bool expected) + { + const string name0 = "name0"; + const string name1 = "name1"; + BooleanType type = NHibernateUtil.Boolean; + var session = Substitute.For(); + var reader = Substitute.For(); + reader[name0].Returns(expected); + reader[name1].Returns(expected); + + var result0 = type.Get(reader, name0, session); + var result1 = type.Get(reader, name1, session); + + Assert.AreEqual(expected, (bool) result0); + Assert.AreSame(result0, result1); + } + + [Test] + public void DefaultValue() + { + BooleanType type = NHibernateUtil.Boolean; + + var result0 = type.DefaultValue; + var result1 = type.DefaultValue; + + Assert.IsFalse((bool) result0); + Assert.AreSame(result0, result1); + } + + [Theory] + public void StringToObject(bool expected) + { + BooleanType type = NHibernateUtil.Boolean; + + var result0 = type.StringToObject(expected.ToString()); + var result1 = type.StringToObject(expected.ToString()); + + Assert.AreEqual(expected, result0); + Assert.AreSame(result0, result1); + } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/TypesTest/CharBooleanTypeFixture.cs b/src/NHibernate.Test/TypesTest/CharBooleanTypeFixture.cs new file mode 100644 index 00000000000..d4448ad6023 --- /dev/null +++ b/src/NHibernate.Test/TypesTest/CharBooleanTypeFixture.cs @@ -0,0 +1,71 @@ +using System.Data.Common; +using NHibernate.Engine; +using NHibernate.SqlTypes; +using NHibernate.Type; +using NSubstitute; +using NUnit.Framework; + +namespace NHibernate.Test.TypesTest +{ + [TestFixture] + public sealed class CharBooleanTypeFixture + { + [Theory] + public void GetByIndex(bool expected) + { + const int index0 = 0; + const int index1 = 1; + CharBooleanType type =new CharBooleanTypeStub(); + var session = Substitute.For(); + var reader = Substitute.For(); + reader[index0].Returns(expected.ToString()); + reader[index1].Returns(expected.ToString()); + + var result0 = type.Get(reader, index0, session); + var result1 = type.Get(reader, index1, session); + + Assert.AreEqual(expected, (bool) result0); + Assert.AreSame(result0, result1); + } + + [Theory] + public void GetByName(bool value) + { + const string name = "0"; + const int index = 0; + object expected = value; + CharBooleanType type = Substitute.ForPartsOf(); + var session = Substitute.For(); + var reader = Substitute.For(); + reader.GetOrdinal(name).Returns(index); + type.Get(reader, index, Arg.Any()).Returns(expected); + + var result = type.Get(reader, name, session); + + Assert.AreSame(expected, result); + } + + [Theory] + public void StringToObject(bool expected) + { + CharBooleanType type = new CharBooleanTypeStub(); + + var result0 = type.StringToObject(expected.ToString()); + var result1 = type.StringToObject(expected.ToString()); + + Assert.AreEqual(expected, result0); + Assert.AreSame(result0, result1); + } + + public class CharBooleanTypeStub : CharBooleanType + { + public CharBooleanTypeStub() : base(new AnsiStringFixedLengthSqlType()) + { + } + + protected override string TrueString => true.ToString(); + + protected override string FalseString => false.ToString(); + } + } +} diff --git a/src/NHibernate/Type/BooleanType.cs b/src/NHibernate/Type/BooleanType.cs index f3333f805b9..5b68c48cab5 100644 --- a/src/NHibernate/Type/BooleanType.cs +++ b/src/NHibernate/Type/BooleanType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using System.Runtime.CompilerServices; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -13,6 +14,9 @@ namespace NHibernate.Type [Serializable] public class BooleanType : PrimitiveType, IDiscriminatorType { + protected static readonly object TrueObject = true; + protected static readonly object FalseObject = false; + /// /// Initialize a new instance of the BooleanType /// @@ -36,12 +40,12 @@ public BooleanType(AnsiStringFixedLengthSqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return Convert.ToBoolean(rs[index]); + return GetBooleanAsObject(Convert.ToBoolean(rs[index])); } public override object Get(DbDataReader rs, string name, ISessionImplementor session) { - return Convert.ToBoolean(rs[name]); + return GetBooleanAsObject(Convert.ToBoolean(rs[name])); } public override System.Type PrimitiveClass @@ -59,15 +63,9 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme cmd.Parameters[index].Value = (bool) value; } - public override string Name - { - get { return "Boolean"; } - } + public override string Name => "Boolean"; - public override object DefaultValue - { - get { return false; } - } + public override object DefaultValue => FalseObject; public override string ObjectToSQLString(object value, Dialect.Dialect dialect) { @@ -89,7 +87,13 @@ public virtual object StringToObject(string xml) [Obsolete("This method has no more usages and will be removed in a future version.")] public override object FromStringValue(string xml) { - return bool.Parse(xml); + return GetBooleanAsObject(bool.Parse(xml)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static object GetBooleanAsObject(bool value) + { + return value ? TrueObject : FalseObject; } } } diff --git a/src/NHibernate/Type/CharBooleanType.cs b/src/NHibernate/Type/CharBooleanType.cs index 9cde87c6697..53dc6a9abb3 100644 --- a/src/NHibernate/Type/CharBooleanType.cs +++ b/src/NHibernate/Type/CharBooleanType.cs @@ -3,7 +3,6 @@ using System.Data.Common; using NHibernate.Engine; using NHibernate.SqlTypes; -using NHibernate.Util; namespace NHibernate.Type { @@ -37,7 +36,7 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi } else { - return code.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase); + return GetBooleanAsObject(code.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase)); } } @@ -68,11 +67,11 @@ public override object StringToObject(String xml) { if (string.Equals(TrueString, xml, StringComparison.InvariantCultureIgnoreCase)) { - return true; + return TrueObject; } else if (string.Equals(FalseString, xml, StringComparison.InvariantCultureIgnoreCase)) { - return false; + return FalseObject; } else { From bb1e8b1d3ca080b111e8f704d682b7ea9a1c5515 Mon Sep 17 00:00:00 2001 From: Evgeny Akhtimirov Date: Mon, 6 Feb 2023 13:58:23 +0300 Subject: [PATCH 2/3] fixed few of deepsource's founds --- src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs | 5 +---- src/NHibernate/Type/BooleanType.cs | 10 ++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs b/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs index feaacf8c48b..cd124b00d0e 100644 --- a/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs +++ b/src/NHibernate.Test/TypesTest/BooleanTypeFixture.cs @@ -12,10 +12,7 @@ namespace NHibernate.Test.TypesTest [TestFixture] public class BooleanTypeFixture : TypeFixtureBase { - protected override string TypeName - { - get { return "Boolean"; } - } + protected override string TypeName => "Boolean"; /// /// Verify Equals will correctly determine when the property diff --git a/src/NHibernate/Type/BooleanType.cs b/src/NHibernate/Type/BooleanType.cs index 5b68c48cab5..2a154211b7b 100644 --- a/src/NHibernate/Type/BooleanType.cs +++ b/src/NHibernate/Type/BooleanType.cs @@ -48,15 +48,9 @@ public override object Get(DbDataReader rs, string name, ISessionImplementor ses return GetBooleanAsObject(Convert.ToBoolean(rs[name])); } - public override System.Type PrimitiveClass - { - get { return typeof(bool); } - } + public override System.Type PrimitiveClass => typeof(bool); - public override System.Type ReturnedClass - { - get { return typeof(bool); } - } + public override System.Type ReturnedClass => typeof(bool); public override void Set(DbCommand cmd, object value, int index, ISessionImplementor session) { From 166ec54a6c8409d32f5e12abd41e4203158dae91 Mon Sep 17 00:00:00 2001 From: Evgeny Akhtimirov Date: Mon, 6 Feb 2023 20:36:56 +0300 Subject: [PATCH 3/3] Generate async files --- .../Async/TypesTest/BooleanTypeFixture.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/NHibernate.Test/Async/TypesTest/BooleanTypeFixture.cs b/src/NHibernate.Test/Async/TypesTest/BooleanTypeFixture.cs index ae41f04a43a..85b11c47f27 100644 --- a/src/NHibernate.Test/Async/TypesTest/BooleanTypeFixture.cs +++ b/src/NHibernate.Test/Async/TypesTest/BooleanTypeFixture.cs @@ -8,8 +8,10 @@ //------------------------------------------------------------------------------ -using System; +using System.Data.Common; +using NHibernate.Engine; using NHibernate.Type; +using NSubstitute; using NUnit.Framework; namespace NHibernate.Test.TypesTest @@ -21,10 +23,7 @@ namespace NHibernate.Test.TypesTest [TestFixture] public class BooleanTypeFixtureAsync : TypeFixtureBase { - protected override string TypeName - { - get { return "Boolean"; } - } + protected override string TypeName => "Boolean"; [Test] public async Task ReadWriteAsync() @@ -48,4 +47,4 @@ public async Task ReadWriteAsync() s.Close(); } } -} \ No newline at end of file +}