From e6f4f3e16d9b6e1a4649457625a5f04cacbcdb19 Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Wed, 21 Feb 2024 19:30:03 +0000 Subject: [PATCH] Improved datamodel segment performance --- .../Models/Profile/DataModel/DataModelPath.cs | 35 ++++++++++++------- .../Profile/DataModel/DataModelPathSegment.cs | 7 ++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index 681ddb923..4375d2d73 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -13,7 +14,7 @@ namespace Artemis.Core; /// public class DataModelPath : IStorageModel, IDisposable { - private readonly LinkedList _segments; + private readonly List _segments; private Expression>? _accessorLambda; private bool _disposed; @@ -27,7 +28,7 @@ public class DataModelPath : IStorageModel, IDisposable Path = ""; Entity = new DataModelPathEntity(); - _segments = new LinkedList(); + _segments = new List(); Save(); Initialize(); @@ -45,7 +46,7 @@ public class DataModelPath : IStorageModel, IDisposable Path = path ?? throw new ArgumentNullException(nameof(path)); Entity = new DataModelPathEntity(); - _segments = new LinkedList(); + _segments = new List(); Save(); Initialize(); @@ -65,7 +66,7 @@ public class DataModelPath : IStorageModel, IDisposable Path = dataModelPath.Path; Entity = new DataModelPathEntity(); - _segments = new LinkedList(); + _segments = new List(); Save(); Initialize(); @@ -81,7 +82,7 @@ public class DataModelPath : IStorageModel, IDisposable Path = entity.Path; Entity = entity; - _segments = new LinkedList(); + _segments = new List(); Load(); Initialize(); @@ -106,12 +107,12 @@ public class DataModelPath : IStorageModel, IDisposable /// /// Gets a boolean indicating whether all are valid /// - public bool IsValid => Segments.Any() && Segments.All(p => p.Type != DataModelPathSegmentType.Invalid); - + public bool IsValid => _segments.Count != 0 && _segments.All(p => p.Type != DataModelPathSegmentType.Invalid); + /// /// Gets a read-only list of all segments of this path /// - public IReadOnlyCollection Segments => _segments.ToList().AsReadOnly(); + public IReadOnlyCollection Segments => _segments; /// /// Gets the entity used for persistent storage @@ -254,10 +255,14 @@ public class DataModelPath : IStorageModel, IDisposable return; Target.AddDataModelPath(this); + Debug.Assert(_segments.Count == 0, "Segments should be cleared before initializing"); DataModelPathSegment startSegment = new(this, "target", "target"); - startSegment.Node = _segments.AddFirst(startSegment); + _segments.Add(startSegment); + //store the previous segment to link them together + DataModelPathSegment previous = startSegment; + // On an empty path don't bother processing segments if (!string.IsNullOrWhiteSpace(Path)) { @@ -265,10 +270,14 @@ public class DataModelPath : IStorageModel, IDisposable for (int index = 0; index < segments.Length; index++) { string identifier = segments[index]; - LinkedListNode node = _segments.AddLast( - new DataModelPathSegment(this, identifier, string.Join('.', segments.Take(index + 1))) - ); - node.Value.Node = node; + DataModelPathSegment segment = new(this, identifier, string.Join('.', segments.Take(index + 1))); + // Set the 'next' pointer on the previous segment to the current segment + previous.Next = segment; + // Set the 'previous' pointer on the current segment to the previous segment + segment.Previous = previous; + _segments.Add(segment); + // The current segment becomes the previous segment for the next iteration + previous = segment; } } diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs index 464bbb58c..1d9ecccd6 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs @@ -55,16 +55,15 @@ public class DataModelPathSegment : IDisposable /// /// Gets the previous segment in the path /// - public DataModelPathSegment? Previous => Node?.Previous?.Value; + public DataModelPathSegment? Previous { get; set; } /// /// Gets the next segment in the path /// - public DataModelPathSegment? Next => Node?.Next?.Value; + public DataModelPathSegment? Next { get; set; } internal Func? Accessor { get; set; } - internal LinkedListNode? Node { get; set; } - + /// /// Returns the current value of the path up to this segment ///