Skip to content

Commit

Permalink
Performance update - Add IEquatable interface for DataValue (#1577)
Browse files Browse the repository at this point in the history
* Add IEquatable interface for DataValue, StatusCode and NumericRange types

- Performance update

Implement strongly typed Equals() method and IEquatable for DataValue, StatusCode and NumericRange types so no boxing is required.
This brings a performance improvement for servers with high number of dynamic nodes and monitored items created where the compare method of DataValue is called intensively (100k -200k/sec)
  • Loading branch information
AlinMoldovean committed Nov 5, 2021
1 parent 7acddc0 commit ea3444b
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 14 deletions.
49 changes: 48 additions & 1 deletion Stack/Opc.Ua.Core/Types/BuiltIn/DataValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace Opc.Ua
/// <seealso cref="Variant"/>
/// <seealso cref="StatusCode"/>
[DataContract(Namespace = Namespaces.OpcUaXsd)]
public class DataValue : IFormattable
public class DataValue : IFormattable, IEquatable<DataValue>
{
#region Constructors
/// <summary>
Expand Down Expand Up @@ -245,6 +245,53 @@ public override bool Equals(object obj)

return Utils.IsEqual(this.m_value.Value, value.m_value.Value);
}

return false;
}

/// <summary>
/// Determines if the specified object is equal to the object.
/// </summary>
/// <remarks>
/// Determines if the specified object is equal to the object.
/// </remarks>
/// <param name="other">The DataValue to compare to *this*</param>
public bool Equals(DataValue other)
{
if (Object.ReferenceEquals(this, other))
{
return true;
}

if (other != null)
{
if (this.m_statusCode != other.m_statusCode)
{
return false;
}

if (this.m_serverTimestamp != other.m_serverTimestamp)
{
return false;
}

if (this.m_sourceTimestamp != other.m_sourceTimestamp)
{
return false;
}

if (this.m_serverPicoseconds != other.m_serverPicoseconds)
{
return false;
}

if (this.m_sourcePicoseconds != other.m_sourcePicoseconds)
{
return false;
}

return Utils.IsEqual(this.m_value.Value, other.m_value.Value);
}

return false;
}
Expand Down
40 changes: 33 additions & 7 deletions Stack/Opc.Ua.Core/Types/BuiltIn/StatusCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ namespace Opc.Ua
/// <br/></para>
/// </remarks>
[DataContract(Name = "StatusCode", Namespace = Namespaces.OpcUaXsd)]
public struct StatusCode : IComparable, IFormattable
public struct StatusCode : IComparable, IFormattable,
IComparable<StatusCode>, IEquatable<StatusCode>
{
#region Constructors

Expand Down Expand Up @@ -426,6 +427,12 @@ public StatusCode SetAggregateBits(AggregateBits bits)
/// <param name="obj">The object to compare to *this* object</param>
public int CompareTo(object obj)
{
// compare codes
if (obj is StatusCode)
{
return m_code.CompareTo(((StatusCode)obj).m_code);
}

// check for null.
if (obj == null)
{
Expand All @@ -438,15 +445,22 @@ public int CompareTo(object obj)
return m_code.CompareTo((uint)obj);
}

// compare codes.
if (obj is StatusCode)
{
return m_code.CompareTo(((StatusCode)obj).m_code);
}

// objects not comparable.
return -1;
}

/// <summary>
/// Compares the instance to another object.
/// </summary>
/// <remarks>
/// Compares the instance to another object.
/// </remarks>
/// <param name="other">The StatusCode to compare to *this* object</param>
public int CompareTo(StatusCode other)
{
// check for status code.
return m_code.CompareTo(other.Code);
}
#endregion

#region IFormattable Members
Expand Down Expand Up @@ -491,6 +505,18 @@ public override bool Equals(object obj)
return CompareTo(obj) == 0;
}

/// <summary>
/// Determines if the specified object is equal to the object.
/// </summary>
/// <remarks>
/// Determines if the specified object is equal to the object.
/// </remarks>
/// <param name="other">The StatusCode to compare to *this* object</param>
public bool Equals(StatusCode other)
{
return CompareTo(other) == 0;
}

/// <summary>
/// Returns a unique hashcode for the object.
/// </summary>
Expand Down
22 changes: 16 additions & 6 deletions Stack/Opc.Ua.Core/Types/Utils/NumericRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Opc.Ua
/// <remarks>
/// A class that stores a numeric range.
/// </remarks>
public struct NumericRange : IFormattable
public struct NumericRange : IFormattable, IEquatable<NumericRange>
{
#region Constructors
/// <summary>
Expand Down Expand Up @@ -268,14 +268,24 @@ public bool EnsureValid(int count)
/// <param name="obj">The object to test against this</param>
public override bool Equals(object obj)
{
NumericRange? range = obj as NumericRange?;

if (range == null)
if (obj is NumericRange)
{
return false;
return this.Equals((NumericRange)obj);
}

return (range.Value.m_begin == m_begin) && (range.Value.m_end == m_end);
return false;
}

/// <summary>
/// Returns true if the objects are equal.
/// </summary>
/// <remarks>
/// Returns true if the objects are equal.
/// </remarks>
/// <param name="other">The NumericRange to test against this</param>
public bool Equals(NumericRange other)
{
return (other.m_begin == m_begin) && (other.m_end == m_end);
}

/// <summary>
Expand Down

0 comments on commit ea3444b

Please sign in to comment.